microsoft/autogen · error · RuntimeError
Runtime is not started
Error message
Runtime is not started
What it means
stop() raises RuntimeError when self._run_context is None, meaning the runtime's processing loop is not currently running. Stopping requires an active run context; stopping an idle/never-started (or already-stopped) runtime is an error, not a no-op.
Source
Thrown at python/packages/autogen-core/src/autogen_core/_single_threaded_agent_runtime.py:836
"""
if self._run_context is not None:
raise RuntimeError("Runtime is already started")
self._run_context = RunContext(self)
async def close(self) -> None:
"""Calls :meth:`stop` if applicable and the :meth:`Agent.close` method on all instantiated agents"""
# stop the runtime if it hasn't been stopped yet
if self._run_context is not None:
await self.stop()
# close all the agents that have been instantiated
for agent_id in self._instantiated_agents:
agent = await self._get_agent(agent_id)
await agent.close()
async def stop(self) -> None:
"""Immediately stop the runtime message processing loop. The currently processing message will be completed, but all others following it will be discarded."""
if self._run_context is None:
raise RuntimeError("Runtime is not started")
try:
await self._run_context.stop()
finally:
self._run_context = None
self._message_queue = Queue()
async def stop_when_idle(self) -> None:
"""Stop the runtime message processing loop when there is
no outstanding message being processed or queued. This is the most common way to stop the runtime."""
if self._run_context is None:
raise RuntimeError("Runtime is not started")
try:
await self._run_context.stop_when_idle()
finally:
self._run_context = None
self._message_queue = Queue()View on GitHub (pinned to 027ecf0a37)
Solutions
- Call stop() exactly once per start(); track lifecycle in your orchestrator with a flag or use try/except RuntimeError in cleanup as a deliberate idempotency guard
- Prefer await runtime.close() for teardown: it stops only if not already stopped and also closes agents
- Ensure close()/stop() are not both invoked in the same teardown sequence for the stop portion
Example fix
# before await runtime.stop_when_idle() await runtime.stop() # RuntimeError # after await runtime.stop_when_idle() await runtime.close() # safe: no-ops the stop portion, closes agents
Defensive patterns
Strategy: try-catch
Validate before calling
def can_stop(runtime) -> bool:
return runtime._run_context is not None Try / catch
try:
await runtime.stop()
except RuntimeError as e:
if "not started" in str(e):
pass # already stopped; idempotent teardown
else:
raise Prevention
- Prefer close() for teardown (it stops only if needed and closes agents)
- Run stop in exactly one place (success path or finally, not both unguarded)
- Track runtime lifecycle state in your app if you stop at multiple points
When it happens
Trigger: Calling await runtime.stop() before any start(), after stop()/stop_when_idle() already completed, or after close() (which itself calls stop when applicable). Double-stop in cleanup paths is the most common form.
Common situations: Cleanup/teardown code running on both the success and exception paths so stop() executes twice; orchestrators that stop at end-of-task and again at shutdown; tests tearing down a runtime that a previous line already stopped.
Related errors
- Runtime is already started
- Agent is already bound to a different runtime
- ClosureAgent must be instantiated within the context of an A
- Message type {type(message)} not in target types {target_typ
- Return type {type(return_value)} not in return types {return
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/ec7ad5e2b7c034ed.
Report an issue: GitHub.