# Buggy code
def getChanges(self, request):
    """
    Reponds only to POST events and starts the build process

    :arguments:
        request
            the http request object
    """
    expected_secret = isinstance(self.options, dict) and self.options.get("secret")
    if expected_secret:
        received_secret = request.getHeader(_HEADER_GITLAB_TOKEN)
        received_secret = bytes2NativeString(received_secret)
        if received_secret != expected_secret:
            raise ValueError("Invalid secret")
    try:
        payload = json.load(request.content)
    except Exception as e:
        raise ValueError("Error loading JSON: " + str(e))
    event_type = request.getHeader(_HEADER_EVENT)
    event_type = bytes2NativeString(event_type)
    # newer version of gitlab have a object_kind parameter,
    # which allows not to use the http header
    event_type = payload.get("object_kind", event_type)
    project = request.args.get("project", [""])[0]
    codebase = request.args.get("codebase", [None])[0]
    if event_type in ("push", "tag_push", "Push Hook"):
        user = payload["user_name"]
        repo = payload["repository"]["name"]
        repo_url = payload["repository"]["url"]
        changes = self._process_change(
            payload, user, repo, repo_url, project, event_type, codebase=codebase
        )
    elif event_type == "merge_request":
        changes = self._process_merge_request_change(
            payload, project, event_type, codebase=codebase
        )
    else:
        changes = []
    if changes:
        log.msg(
            "Received {} changes from {} gitlab event".format(len(changes), event_type)
        )
    return (changes, "git")


# Traceback (builtins.KeyError)
Traceback (most recent call last):
File "/opt/buildbot/lib/python3.5/site-packages/twisted/web/server.py", line 235, in render
body = resrc.render(self)
File "/opt/buildbot/lib/python3.5/site-packages/twisted/web/resource.py", line 250, in render
return m(request)
File "/opt/buildbot/lib/python3.5/site-packages/buildbot/www/change_hook.py", line 81, in render_POST
d = self.getAndSubmitChanges(request)
File "/opt/buildbot/lib/python3.5/site-packages/twisted/internet/defer.py", line 1532, in unwindGenerator
return _inlineCallbacks(None, gen, Deferred())
--- <exception caught here> ---
File "/opt/buildbot/lib/python3.5/site-packages/twisted/internet/defer.py", line 1384, in _inlineCallbacks
result = result.throwExceptionIntoGenerator(g)
File "/opt/buildbot/lib/python3.5/site-packages/twisted/python/failure.py", line 393, in throwExceptionIntoGenerator
return g.throw(self.type, self.value, self.tb)
File "/opt/buildbot/lib/python3.5/site-packages/buildbot/www/change_hook.py", line 107, in getAndSubmitChanges
changes, src = yield self.getChanges(request)
builtins.KeyError: 'payload'

# Fixed code
def getChanges(self, request):
    """
    Reponds only to POST events and starts the build process

    :arguments:
        request
            the http request object
    """
    expected_secret = isinstance(self.options, dict) and self.options.get("secret")
    if expected_secret:
        received_secret = request.getHeader(_HEADER_GITLAB_TOKEN)
        received_secret = bytes2unicode(received_secret)
        if received_secret != expected_secret:
            raise ValueError("Invalid secret")
    try:
        content = request.content.read()
        payload = json.loads(bytes2unicode(content))
    except Exception as e:
        raise ValueError("Error loading JSON: " + str(e))
    event_type = request.getHeader(_HEADER_EVENT)
    event_type = bytes2unicode(event_type)
    # newer version of gitlab have a object_kind parameter,
    # which allows not to use the http header
    event_type = payload.get("object_kind", event_type)
    project = request.args.get("project", [""])[0]
    codebase = request.args.get("codebase", [None])[0]
    if event_type in ("push", "tag_push", "Push Hook"):
        user = payload["user_name"]
        repo = payload["repository"]["name"]
        repo_url = payload["repository"]["url"]
        changes = self._process_change(
            payload, user, repo, repo_url, project, event_type, codebase=codebase
        )
    elif event_type == "merge_request":
        changes = self._process_merge_request_change(
            payload, project, event_type, codebase=codebase
        )
    else:
        changes = []
    if changes:
        log.msg(
            "Received {} changes from {} gitlab event".format(len(changes), event_type)
        )
    return (changes, "git")