{"record":{"id":"9865f12f531571f2","repo":"microsoft/autogen","slug":"host-runtime-is-not-started","errorCode":null,"errorMessage":"Host runtime is not started.","messagePattern":"Host runtime is not started\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-ext/src/autogen_ext/runtimes/grpc/_worker_runtime_host.py","lineNumber":42,"sourceCode":"        self._server.add_insecure_port(address)\n        self._address = address\n        self._serve_task: asyncio.Task[None] | None = None\n\n    async def _serve(self) -> None:\n        await self._server.start()\n        logger.info(f\"Server started at {self._address}.\")\n        await self._server.wait_for_termination()\n\n    def start(self) -> None:\n        \"\"\"Start the server in a background task.\"\"\"\n        if self._serve_task is not None:\n            raise RuntimeError(\"Host runtime is already started.\")\n        self._serve_task = asyncio.create_task(self._serve())\n\n    async def stop(self, grace: int = 5) -> None:\n        \"\"\"Stop the server.\"\"\"\n        if self._serve_task is None:\n            raise RuntimeError(\"Host runtime is not started.\")\n        await self._server.stop(grace=grace)\n        self._serve_task.cancel()\n        try:\n            await self._serve_task\n        except asyncio.CancelledError:\n            pass\n        logger.info(\"Server stopped.\")\n        self._serve_task = None\n\n    async def stop_when_signal(\n        self, grace: int = 5, signals: Sequence[signal.Signals] = (signal.SIGTERM, signal.SIGINT)\n    ) -> None:\n        \"\"\"Stop the server when a signal is received.\"\"\"\n        if self._serve_task is None:\n            raise RuntimeError(\"Host runtime is not started.\")\n        # Set up signal handling for graceful shutdown.\n        loop = asyncio.get_running_loop()\n        shutdown_event = asyncio.Event()","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-ext/src/autogen_ext/runtimes/grpc/_worker_runtime_host.py#L24-L60","documentation":"GrpcWorkerAgentRuntimeHost.stop() tears the server down (grpc stop with grace, cancel of the serve task) but only if a serve task exists: when self._serve_task is None it raises RuntimeError('Host runtime is not started.'). This catches stopping a host that was never started or was already stopped (stop() resets _serve_task to None, so a second stop() also raises).","triggerScenarios":"Calling await host.stop() before any host.start(); calling stop() twice; calling stop() after a previous stop() completed (the flag was cleared); cleanup code in finally blocks after startup failed early.","commonSituations":"Symmetric cleanup in try/finally where start() failed so the task never existed; double teardown in tests (fixture finalizer plus explicit stop); signal handlers racing with manual shutdown code both calling stop().","solutions":["Only call stop() after a successful start(); track a started flag and clear it after stopping","Make teardown idempotent: catch RuntimeError from stop() and ignore it when the intent is 'ensure stopped'","Sequence restarts as start -> stop -> start, never stop on a never-started or already-stopped host","In signal handlers, coordinate with manual shutdown via an asyncio.Event so stop() runs once"],"exampleFix":"# before\nawait host.stop()  # RuntimeError: never started (or already stopped)\n\n# after\nstarted = False\nhost.start(); started = True\n# ... teardown:\nif started:\n    await host.stop()\n    started = False\n# or simply:\ntry:\n    await host.stop()\nexcept RuntimeError:\n    pass","handlingStrategy":"try-catch","validationCode":"started = False\nhost.start(); started = True\n# ... later:\nif started:\n    await host.stop(); started = False","typeGuard":null,"tryCatchPattern":"try:\n    await host.stop()\nexcept RuntimeError as e:\n    if 'not started' in str(e):\n        pass  # never started or already stopped — nothing to do\n    else:\n        raise","preventionTips":["Track a started flag and clear it after every stop","Make teardown idempotent (catch the 'not started' RuntimeError)","Only call stop() after a successful start()","Coordinate signal handlers and manual shutdown so stop() runs once"],"tags":["lifecycle","grpc","teardown","host"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}