{"id":"d052c15373419ffc","repo":"aio-libs/aiohttp","slug":"session-and-connector-have-to-use-same-event-loop","errorCode":null,"errorMessage":"Session and connector have to use same event loop","messagePattern":"Session and connector have to use same event loop","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":377,"sourceCode":"                DeprecationWarning,\n                stacklevel=2,\n            )\n\n        if connector is None:\n            connector = TCPConnector(ssl_shutdown_timeout=ssl_shutdown_timeout)\n        # Initialize these three attrs before raising any exception,\n        # they are used in __del__\n        self._connector = connector\n        self._loop = loop\n        if loop.get_debug():\n            self._source_traceback: traceback.StackSummary | None = (\n                traceback.extract_stack(sys._getframe(1))\n            )\n        else:\n            self._source_traceback = None\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector have to use same event loop\")\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar()\n        self._cookie_jar = cookie_jar\n\n        if cookies:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector_owner = connector_owner\n        self._version = version\n        self._json_serialize = json_serialize\n        self._json_serialize_bytes = json_serialize_bytes\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L359-L395","documentation":"Raised in ClientSession.__init__ (client.py:377) when the user-supplied `connector` was bound to a different asyncio event loop than the one currently running when the session is constructed. aiohttp pins the connector to its loop at creation; the session refuses to operate across loops to avoid cross-loop I/O corruption. The guard compares `connector._loop` to the loop returned by `asyncio.get_running_loop()` at session construction time.","triggerScenarios":"Creating a `TCPConnector()` in one event loop/coroutine and then constructing `ClientSession(connector=that_connector)` inside a different loop (e.g., created the connector at import time outside any loop, or reused a connector across `asyncio.run()` calls).","commonSituations":"Module-level `connector = TCPConnector()` evaluated before any loop exists; reusing a connector after `asyncio.run()` tears down and starts a fresh loop; mixing threads with separate loops; test fixtures that build the connector in `setUp` but run the test in a new loop.","solutions":["Construct both the connector and the session inside the same `async` function / same event loop.","Drop the explicit `connector=` argument and let the session create its own `TCPConnector()` (it does so at client.py:364 when `connector is None`).","If you must share a connector, create it lazily inside the running loop and reuse it only within that loop's lifetime."],"exampleFix":"// before\nconnector = aiohttp.TCPConnector()  # built at import time, no loop\nasync def main():\n    session = aiohttp.ClientSession(connector=connector)\n// after\nasync def main():\n    connector = aiohttp.TCPConnector()\n    session = aiohttp.ClientSession(connector=connector)","handlingStrategy":"validation","validationCode":"import asyncio\n\ndef same_loop(connector) -> bool:\n    try:\n        running = asyncio.get_running_loop()\n    except RuntimeError:\n        return False\n    return connector._loop is running","typeGuard":null,"tryCatchPattern":"try:\n    session = aiohttp.ClientSession(connector=connector)\nexcept RuntimeError as e:\n    if 'same event loop' in str(e):\n        # rebuild connector in the current loop\n        connector = aiohttp.TCPConnector()\n        session = aiohttp.ClientSession(connector=connector)\n    else:\n        raise","preventionTips":["Construct the connector and session inside the same async function.","Never create connectors at module import time.","Prefer letting ClientSession create its own connector (omit the `connector=` arg).","In tests, use aiohttp's pytest-aiohttp plugin which manages loop/session fixtures correctly."],"tags":["client","asyncio","event-loop","configuration"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}