# Buggy code
def _configure_node_from_config(self, config):
    """
    Startup elements in the node as specified in the provided node configuration.
    """
    self.log.info("Configuring node from local configuration ...")

    # get contoller configuration subpart
    controller = config.get("controller", {})

    # start Manhole in node controller
    if "manhole" in controller:
        yield self._controller.call(
            "crossbar.start_manhole", controller["manhole"], options=CallOptions()
        )
        self.log.debug("controller: manhole started")

    # startup all workers
    workers = config.get("workers", [])
    if len(workers):
        self.log.info("Starting {nworkers} workers ...", nworkers=len(workers))
    else:
        self.log.info("No workers configured!")
    for worker in workers:
        # worker ID
        if "id" in worker:
            worker_id = worker.pop("id")
        else:
            worker_id = "worker-{:03d}".format(self._worker_no)
            self._worker_no += 1

        # worker type - a type of working process from the following fixed list
        worker_type = worker["type"]
        assert worker_type in self._native_workers
        worker_cfg = self._native_workers[worker_type]

        # set logname depending on worker type
        worker_logname = "{} '{}'".format(worker_cfg["logname"], worker_id)

        # any worker specific options
        worker_options = worker.get("options", {})

        # now actually start the worker ..
        yield self._controller.call(
            "crossbar.start_worker",
            worker_id,
            worker_type,
            worker_options,
            options=CallOptions(),
        )

        # native worker processes setup
        if worker_type in self._native_workers:
            # setup native worker generic stuff
            method_name = "_configure_native_worker_{}".format(
                worker_type.replace("-", "_")
            )
            try:
                config_fn = getattr(self, method_name)
            except AttributeError:
                raise ValueError(
                    "A native worker of type '{}' is configured but "
                    "there is no method '{}' on {}".format(
                        worker_type, method_name, type(self)
                    )
                )
            yield config_fn(worker_logname, worker_id, worker)

    self.log.info("Local node configuration applied successfully!")


# Traceback (builtins.AssertionError)
2017-09-05T14:52:34+0200 [Controller  15960] Starting 2 workers ...
2017-09-05T14:52:34+0200 [Controller  15960] Router worker "worker-001" starting ..
2017-09-05T14:52:34+0200 [Router      15969] Started Router worker "worker-001" [crossbar.worker.router.RouterWorkerSession / CPython-EPollReactor]
2017-09-05T14:52:34+0200 [Router      15969] Router worker "worker-001" session 3303279962187294 initializing ..
2017-09-05T14:52:34+0200 [Router      15969] Registered 35 procedures
2017-09-05T14:52:34+0200 [Router      15969] Router worker "worker-001" session ready
2017-09-05T14:52:34+0200 [Controller  15960] Router worker "worker-001" process 15969 started
2017-09-05T14:52:34+0200 [Router      15969] RouterServiceSession ready [configured on_ready fired]
2017-09-05T14:52:34+0200 [Router      15969] Realm 'realm1' started
2017-09-05T14:52:34+0200 [Controller  15960] Router 'worker-001': realm 'realm-001' (named 'realm1') started
2017-09-05T14:52:34+0200 [Router      15969] role role-001 on realm realm-001 started
2017-09-05T14:52:34+0200 [Controller  15960] Router 'worker-001': role 'role-001' (named 'authenticator') started on realm 'realm-001'
2017-09-05T14:52:34+0200 [Router      15969] role role-002 on realm realm-001 started
2017-09-05T14:52:34+0200 [Controller  15960] Router 'worker-001': role 'role-002' (named 'public') started on realm 'realm-001'
2017-09-05T14:52:34+0200 [Router      15969] started component: labgrid.remote.authenticator.AuthenticatorSession id=1175882440106437
2017-09-05T14:52:34+0200 [Controller  15960] Router 'worker-001': component 'component-001' started
2017-09-05T14:52:34+0200 [Router      15969] Site starting on 20408
2017-09-05T14:52:34+0200 [Controller  15960] Router 'worker-001': transport 'transport-001' started
2017-09-05T14:52:34+0200 [Controller  15960] Could not startup node: Traceback (most recent call last):
File "/home/phoenix/.virtualenvs/labgrid/lib/python3.6/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/home/phoenix/.virtualenvs/labgrid/lib/python3.6/site-packages/twisted/internet/defer.py", line 1442, in gotResult
_inlineCallbacks(r, g, deferred)
File "/home/phoenix/.virtualenvs/labgrid/lib/python3.6/site-packages/twisted/internet/defer.py", line 1384, in _inlineCallbacks
result = result.throwExceptionIntoGenerator(g)
File "/home/phoenix/.virtualenvs/labgrid/lib/python3.6/site-packages/twisted/python/failure.py", line 393, in throwExceptionIntoGenerator
return g.throw(self.type, self.value, self.tb)
--- <exception caught here> ---
File "/home/phoenix/.virtualenvs/labgrid/lib/python3.6/site-packages/crossbar/controller/node.py", line 597, in start
yield self._startup()
File "/home/phoenix/.virtualenvs/labgrid/lib/python3.6/site-packages/twisted/internet/defer.py", line 1386, in _inlineCallbacks
result = g.send(result)
File "/home/phoenix/.virtualenvs/labgrid/lib/python3.6/site-packages/crossbar/controller/node.py", line 656, in _configure_node_from_config
assert worker_type in self._native_workers
builtins.AssertionError:

# Fixed code
def _configure_node_from_config(self, config):
    """
    Startup elements in the node as specified in the provided node configuration.
    """
    self.log.info("Configuring node from local configuration ...")

    # get contoller configuration subpart
    controller = config.get("controller", {})

    # start Manhole in node controller
    if "manhole" in controller:
        yield self._controller.call(
            "crossbar.start_manhole", controller["manhole"], options=CallOptions()
        )
        self.log.debug("controller: manhole started")

    # startup all workers
    workers = config.get("workers", [])
    if len(workers):
        self.log.info("Starting {nworkers} workers ...", nworkers=len(workers))
    else:
        self.log.info("No workers configured!")

    for worker in workers:
        # worker ID
        if "id" in worker:
            worker_id = worker.pop("id")
        else:
            worker_id = "worker-{:03d}".format(self._worker_no)
            self._worker_no += 1

        # worker type: either a native worker ('router', 'container', ..), or a guest worker ('guest')
        worker_type = worker["type"]

        # native worker processes setup
        if worker_type in self._native_workers:
            # set logname depending on native worker type
            worker_logname = '{} "{}"'.format(
                self._native_workers[worker_type]["logname"], worker_id
            )

            # any worker specific options
            worker_options = worker.get("options", {})

            # now actually start the (native) worker ..
            yield self._controller.call(
                "crossbar.start_worker",
                worker_id,
                worker_type,
                worker_options,
                options=CallOptions(),
            )

            # setup native worker generic stuff
            method_name = "_configure_native_worker_{}".format(
                worker_type.replace("-", "_")
            )
            try:
                config_fn = getattr(self, method_name)
            except AttributeError:
                raise ValueError(
                    "A native worker of type '{}' is configured but "
                    "there is no method '{}' on {}".format(
                        worker_type, method_name, type(self)
                    )
                )
            yield config_fn(worker_logname, worker_id, worker)

        # guest worker processes setup
        elif worker_type == "guest":
            # now actually start the (guest) worker ..

            # FIXME: start_worker() takes the whole configuration item for guest workers, whereas native workers
            # only take the options (which is part of the whole config item for the worker)
            yield self._controller.call(
                "crossbar.start_worker",
                worker_id,
                worker_type,
                worker,
                options=CallOptions(),
            )

        else:
            raise Exception(
                'logic error: unexpected worker_type="{}"'.format(worker_type)
            )

    self.log.info("Local node configuration applied successfully!")