{"record":{"id":"d295a0e1110189b8","repo":"microsoft/semantic-kernel","slug":"self-r-is-bound-to-a-different-event-loop","errorCode":null,"errorMessage":"{self!r} is bound to a different event loop","messagePattern":"(.+?) is bound to a different event loop","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/runtime/in_process/queue.py","lineNumber":28,"sourceCode":"from typing import Generic, TypeVar\n\nfrom semantic_kernel.utils.feature_stage_decorator import experimental\n\n_global_lock = threading.Lock()\n\n\nclass _LoopBoundMixin:\n    _loop = None\n\n    def _get_loop(self) -> asyncio.AbstractEventLoop:\n        loop = asyncio.get_running_loop()\n\n        if self._loop is None:\n            with _global_lock:\n                if self._loop is None:\n                    self._loop = loop\n        if loop is not self._loop:\n            raise RuntimeError(f\"{self!r} is bound to a different event loop\")\n        return loop\n\n\n@experimental\nclass QueueShutDown(Exception):\n    \"\"\"Raised when putting on to or getting from a shut-down Queue.\"\"\"\n\n    pass\n\n\nT = TypeVar(\"T\")\n\n\n@experimental\nclass Queue(_LoopBoundMixin, Generic[T]):\n    \"\"\"A queue class that supports async operations.\"\"\"\n\n    def __init__(self, maxsize: int = 0):","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/runtime/in_process/queue.py#L10-L46","documentation":"_LoopBoundMixin binds a queue (or similar async primitive) to the first event loop it is used on. On subsequent uses, if asyncio.get_running_loop() returns a different loop object, RuntimeError is raised. This prevents cross-loop corruption of internal async state.","triggerScenarios":"Using the same runtime (and its internal Queue) across two different event loops — e.g. starting the runtime in one asyncio loop, then calling runtime methods from a newly created loop. Common with pytest-asyncio when session-scoped fixtures run on different event loops than test-scoped code.","commonSituations":"pytest-asyncio with different event_loop policies per test scope. Running the runtime in one thread/loop and accessing it from another. Jupyter notebooks that create new event loops per cell. asyncio.run() called multiple times in sequence while holding a reference to the same runtime.","solutions":["Ensure the runtime is created, started, used, and stopped all within the same event loop.","In pytest, use a consistent event_loop fixture scope (e.g. function-scoped for both runtime and tests).","Do not reuse a runtime across asyncio.run() calls — create a new instance each time.","If using threads, ensure all runtime access happens on the loop's owning thread."],"exampleFix":"# before\nasync def setup():\n    runtime.start()\n\nasyncio.run(setup())  # binds to loop A\nasync def use():\n    await runtime.send_message(...)  # different loop → raises\nasyncio.run(use())\n\n# after\nasync def main():\n    runtime.start()\n    await runtime.send_message(...)\n    await runtime.stop_when_idle()\n\nasyncio.run(main())  # all on same loop","handlingStrategy":"validation","validationCode":"import asyncio\n\n# Ensure all runtime access happens on the same loop\nloop = asyncio.get_running_loop()\n# Pass this loop reference around; before using the runtime from a new context:\ncurrent_loop = asyncio.get_running_loop()\nif current_loop is not loop:\n    raise RuntimeError('Runtime bound to a different event loop')","typeGuard":"null","tryCatchPattern":"try:\n    await runtime.send_message(msg, recipient)\nexcept RuntimeError as e:\n    if 'bound to a different event loop' in str(e):\n        # Recreate runtime on the current loop\n        runtime = InProcessRuntime()\n        runtime.start()","preventionTips":["Create, start, use, and stop the runtime within a single asyncio.run() call or single event loop.","In pytest-asyncio, use consistent event_loop fixture scopes for runtime and test functions.","Do not share a runtime across threads or across asyncio.run() invocations.","Avoid session-scoped runtime fixtures with function-scoped test loops."],"tags":["agent-runtime","event-loop","asyncio","queue","loop-bound","semantic-kernel"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}