# Buggy code
def on_authorize_success(authorization):
    # check the authorization before ANYTHING else, otherwise
    # we may leak information about already-registered URIs
    # etc.
    if not authorization["allow"]:
        # error reply since session is not authorized to register
        #
        reply = message.Error(
            message.Register.MESSAGE_TYPE,
            register.request,
            ApplicationError.NOT_AUTHORIZED,
            [
                "session is not authorized to register procedure '{0}'".format(
                    register.procedure
                )
            ],
        )

    # get existing registration for procedure / matching strategy - if any
    #
    registration = self._registration_map.get_observation(
        register.procedure, register.match
    )

    # if force_reregister was enabled, we only do any actual
    # kicking of existing registrations *after* authorization
    if registration and not register.force_reregister:
        # there is an existing registration, and that has an
        # invocation strategy that only allows a single callee
        # on a the given registration
        #
        if registration.extra.invoke == message.Register.INVOKE_SINGLE:
            reply = message.Error(
                message.Register.MESSAGE_TYPE,
                register.request,
                ApplicationError.PROCEDURE_ALREADY_EXISTS,
                [
                    "register for already registered procedure '{0}'".format(
                        register.procedure
                    )
                ],
            )
            reply.correlation_id = register.correlation_id
            reply.correlation_uri = register.procedure
            reply.correlation_is_anchor = False
            reply.correlation_is_last = True
            self._router.send(session, reply)
            return

        # there is an existing registration, and that has an
        # invokation strategy different from the one requested
        # by the new callee
        #
        if registration.extra.invoke != register.invoke:
            reply = message.Error(
                message.Register.MESSAGE_TYPE,
                register.request,
                ApplicationError.PROCEDURE_EXISTS_INVOCATION_POLICY_CONFLICT,
                [
                    "register for already registered procedure '{0}' "
                    "with conflicting invocation policy (has {1} and "
                    "{2} was requested)".format(
                        register.procedure, registration.extra.invoke, register.invoke
                    )
                ],
            )
            reply.correlation_id = register.correlation_id
            reply.correlation_uri = register.procedure
            reply.correlation_is_anchor = False
            reply.correlation_is_last = True
            self._router.send(session, reply)
            return

    # this check is a little redundant, because theoretically
    # we already returned (above) if this was False, but for safety...
    if authorization["allow"]:
        registration = self._registration_map.get_observation(
            register.procedure, register.match
        )
        if register.force_reregister and registration:
            for obs in registration.observers:
                self._registration_map.drop_observer(obs, registration)
                kicked = message.Unregistered(
                    0,
                    registration=registration.id,
                    reason="wamp.error.unregistered",
                )
                kicked.correlation_id = register.correlation_id
                kicked.correlation_uri = register.procedure
                kicked.correlation_is_anchor = False
                kicked.correlation_is_last = False
                self._router.send(obs, kicked)
            self._registration_map.delete_observation(registration)

        # ok, session authorized to register. now get the registration
        #
        registration_extra = RegistrationExtra(register.invoke)
        registration_callee_extra = RegistrationCalleeExtra(register.concurrency)
        registration, was_already_registered, is_first_callee = (
            self._registration_map.add_observer(
                session,
                register.procedure,
                register.match,
                registration_extra,
                registration_callee_extra,
            )
        )

        if not was_already_registered:
            self._session_to_registrations[session].add(registration)

        # acknowledge register with registration ID
        #
        reply = message.Registered(register.request, registration.id)
        reply.correlation_id = register.correlation_id
        reply.correlation_uri = register.procedure
        reply.correlation_is_anchor = False

        # publish WAMP meta events, if we have a service session, but
        # not for the meta API itself!
        #
        if (
            self._router._realm
            and self._router._realm.session
            and not registration.uri.startswith("wamp.")
            and (is_first_callee or not was_already_registered)
        ):
            reply.correlation_is_last = False

            # when this message was forwarded from other nodes, exclude all such nodes
            # from receiving the meta event we'll publish below by authid (of the r2r link
            # from the forwarding node connected to this router node)
            exclude_authid = None
            if register.forward_for:
                exclude_authid = [ff["authid"] for ff in register.forward_for]
                self.log.info(
                    "WAMP meta event will be published excluding these authids (from forward_for): {exclude_authid}",
                    exclude_authid=exclude_authid,
                )

            def _publish():
                service_session = self._router._realm.session

                if exclude_authid or self._router.is_traced:
                    options = types.PublishOptions(
                        correlation_id=register.correlation_id,
                        correlation_is_anchor=False,
                        correlation_is_last=False,
                        exclude_authid=exclude_authid,
                    )
                else:
                    options = None

                if is_first_callee:
                    registration_details = {
                        "id": registration.id,
                        "created": registration.created,
                        "uri": registration.uri,
                        "match": registration.match,
                        "invoke": registration.extra.invoke,
                    }
                    service_session.publish(
                        "wamp.registration.on_create",
                        session._session_id,
                        registration_details,
                        options=options,
                    )

                if not was_already_registered:
                    if options:
                        options.correlation_is_last = True

                    service_session.publish(
                        "wamp.registration.on_register",
                        session._session_id,
                        registration.id,
                        options=options,
                    )

            # we postpone actual sending of meta events until we return to this client session
            self._reactor.callLater(0, _publish)

        else:
            reply.correlation_is_last = True

    # send out reply to register requestor
    #
    self._router.send(session, reply)


# Traceback (builtins.KeyError)
Unhandled error in Deferred:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/autobahn/wamp/protocol.py", line 888, in onMessage
txaio.resolve(on_reply, msg.args[0])
File "/usr/local/lib/python3.6/dist-packages/txaio/tx.py", line 468, in resolve
future.callback(result)
File "/usr/local/lib/python3.6/dist-packages/twisted/internet/defer.py", line 460, in callback
self._startRunCallbacks(result)
File "/usr/local/lib/python3.6/dist-packages/twisted/internet/defer.py", line 568, in _startRunCallbacks
self._runCallbacks()
--- <exception caught here> ---
File "/usr/local/lib/python3.6/dist-packages/twisted/internet/defer.py", line 654, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/usr/local/lib/python3.6/dist-packages/crossbar/router/dealer.py", line 441, in on_authorize_success
self._session_to_registrations[session].add(registration)
builtins.KeyError: <crossbar.router.session.RouterSession object at 0x7f653abfaef0>

# Fixed code
def on_authorize_success(authorization):
    # check the authorization before ANYTHING else, otherwise
    # we may leak information about already-registered URIs
    # etc.
    if not authorization["allow"]:
        # error reply since session is not authorized to register
        #
        reply = message.Error(
            message.Register.MESSAGE_TYPE,
            register.request,
            ApplicationError.NOT_AUTHORIZED,
            [
                "session is not authorized to register procedure '{0}'".format(
                    register.procedure
                )
            ],
        )

    # get existing registration for procedure / matching strategy - if any
    #
    registration = self._registration_map.get_observation(
        register.procedure, register.match
    )

    # if the session disconencted while the authorization was
    # being checked, stop
    if session not in self._session_to_registrations:
        # if the session *really* disconnected, it won't have
        # a _session_id any longer, so we double-check
        if session._session_id is not None:
            self.log.error(
                "Session '{session_id}' still appears valid, but isn't in registration map",
                session_id=session._session_id,
            )
        self.log.info(
            "Session vanished while registering '{procedure}'",
            procedure=register.procedure,
        )
        assert registration is None
        return

    # if force_reregister was enabled, we only do any actual
    # kicking of existing registrations *after* authorization
    if registration and not register.force_reregister:
        # there is an existing registration, and that has an
        # invocation strategy that only allows a single callee
        # on a the given registration
        #
        if registration.extra.invoke == message.Register.INVOKE_SINGLE:
            reply = message.Error(
                message.Register.MESSAGE_TYPE,
                register.request,
                ApplicationError.PROCEDURE_ALREADY_EXISTS,
                [
                    "register for already registered procedure '{0}'".format(
                        register.procedure
                    )
                ],
            )
            reply.correlation_id = register.correlation_id
            reply.correlation_uri = register.procedure
            reply.correlation_is_anchor = False
            reply.correlation_is_last = True
            self._router.send(session, reply)
            return

        # there is an existing registration, and that has an
        # invokation strategy different from the one requested
        # by the new callee
        #
        if registration.extra.invoke != register.invoke:
            reply = message.Error(
                message.Register.MESSAGE_TYPE,
                register.request,
                ApplicationError.PROCEDURE_EXISTS_INVOCATION_POLICY_CONFLICT,
                [
                    "register for already registered procedure '{0}' "
                    "with conflicting invocation policy (has {1} and "
                    "{2} was requested)".format(
                        register.procedure, registration.extra.invoke, register.invoke
                    )
                ],
            )
            reply.correlation_id = register.correlation_id
            reply.correlation_uri = register.procedure
            reply.correlation_is_anchor = False
            reply.correlation_is_last = True
            self._router.send(session, reply)
            return

    # this check is a little redundant, because theoretically
    # we already returned (above) if this was False, but for safety...
    if authorization["allow"]:
        registration = self._registration_map.get_observation(
            register.procedure, register.match
        )
        if register.force_reregister and registration:
            for obs in registration.observers:
                self._registration_map.drop_observer(obs, registration)
                kicked = message.Unregistered(
                    0,
                    registration=registration.id,
                    reason="wamp.error.unregistered",
                )
                kicked.correlation_id = register.correlation_id
                kicked.correlation_uri = register.procedure
                kicked.correlation_is_anchor = False
                kicked.correlation_is_last = False
                self._router.send(obs, kicked)
            self._registration_map.delete_observation(registration)

        # ok, session authorized to register. now get the registration
        #
        registration_extra = RegistrationExtra(register.invoke)
        registration_callee_extra = RegistrationCalleeExtra(register.concurrency)
        registration, was_already_registered, is_first_callee = (
            self._registration_map.add_observer(
                session,
                register.procedure,
                register.match,
                registration_extra,
                registration_callee_extra,
            )
        )

        if not was_already_registered:
            self._session_to_registrations[session].add(registration)

        # acknowledge register with registration ID
        #
        reply = message.Registered(register.request, registration.id)
        reply.correlation_id = register.correlation_id
        reply.correlation_uri = register.procedure
        reply.correlation_is_anchor = False

        # publish WAMP meta events, if we have a service session, but
        # not for the meta API itself!
        #
        if (
            self._router._realm
            and self._router._realm.session
            and not registration.uri.startswith("wamp.")
            and (is_first_callee or not was_already_registered)
        ):
            reply.correlation_is_last = False

            # when this message was forwarded from other nodes, exclude all such nodes
            # from receiving the meta event we'll publish below by authid (of the r2r link
            # from the forwarding node connected to this router node)
            exclude_authid = None
            if register.forward_for:
                exclude_authid = [ff["authid"] for ff in register.forward_for]
                self.log.info(
                    "WAMP meta event will be published excluding these authids (from forward_for): {exclude_authid}",
                    exclude_authid=exclude_authid,
                )

            def _publish():
                service_session = self._router._realm.session

                if exclude_authid or self._router.is_traced:
                    options = types.PublishOptions(
                        correlation_id=register.correlation_id,
                        correlation_is_anchor=False,
                        correlation_is_last=False,
                        exclude_authid=exclude_authid,
                    )
                else:
                    options = None

                if is_first_callee:
                    registration_details = {
                        "id": registration.id,
                        "created": registration.created,
                        "uri": registration.uri,
                        "match": registration.match,
                        "invoke": registration.extra.invoke,
                    }
                    service_session.publish(
                        "wamp.registration.on_create",
                        session._session_id,
                        registration_details,
                        options=options,
                    )

                if not was_already_registered:
                    if options:
                        options.correlation_is_last = True

                    service_session.publish(
                        "wamp.registration.on_register",
                        session._session_id,
                        registration.id,
                        options=options,
                    )

            # we postpone actual sending of meta events until we return to this client session
            self._reactor.callLater(0, _publish)

        else:
            reply.correlation_is_last = True

    # send out reply to register requestor
    #
    self._router.send(session, reply)