microsoft/autogen · error · RuntimeError
Host runtime is not started.
Error message
Host runtime is not started.
What it means
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).
Source
Thrown at python/packages/autogen-ext/src/autogen_ext/runtimes/grpc/_worker_runtime_host.py:42
self._server.add_insecure_port(address)
self._address = address
self._serve_task: asyncio.Task[None] | None = None
async def _serve(self) -> None:
await self._server.start()
logger.info(f"Server started at {self._address}.")
await self._server.wait_for_termination()
def start(self) -> None:
"""Start the server in a background task."""
if self._serve_task is not None:
raise RuntimeError("Host runtime is already started.")
self._serve_task = asyncio.create_task(self._serve())
async def stop(self, grace: int = 5) -> None:
"""Stop the server."""
if self._serve_task is None:
raise RuntimeError("Host runtime is not started.")
await self._server.stop(grace=grace)
self._serve_task.cancel()
try:
await self._serve_task
except asyncio.CancelledError:
pass
logger.info("Server stopped.")
self._serve_task = None
async def stop_when_signal(
self, grace: int = 5, signals: Sequence[signal.Signals] = (signal.SIGTERM, signal.SIGINT)
) -> None:
"""Stop the server when a signal is received."""
if self._serve_task is None:
raise RuntimeError("Host runtime is not started.")
# Set up signal handling for graceful shutdown.
loop = asyncio.get_running_loop()
shutdown_event = asyncio.Event()View on GitHub (pinned to 027ecf0a37)
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
Example fix
# before
await host.stop() # RuntimeError: never started (or already stopped)
# after
started = False
host.start(); started = True
# ... teardown:
if started:
await host.stop()
started = False
# or simply:
try:
await host.stop()
except RuntimeError:
pass Defensive patterns
Strategy: try-catch
Validate before calling
started = False
host.start(); started = True
# ... later:
if started:
await host.stop(); started = False Try / catch
try:
await host.stop()
except RuntimeError as e:
if 'not started' in str(e):
pass # never started or already stopped — nothing to do
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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().
Related errors
- Host runtime is already started.
- Connection is not open.
- Runtime is already running.
- Runtime is not running.
- Host connection is not set.
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/9865f12f531571f2.
Report an issue: GitHub.