Report #54978
[bug\_fix] RuntimeError: Task attached to a different loop OR Event loop is closed
Ensure that async objects \(like \`aiohttp.ClientSession\`\) are created within the async context that uses them \(i.e., inside \`async def\` methods\), not in \`\_\_init\_\_\` or at module level. In tests, ensure \`pytest-asyncio\` uses \`scope="function"\` \(default\) to provide a fresh loop per test. The root cause is that async objects bind to the event loop at creation time; if created in one loop \(e.g., previous test\) and used in another \(current test\), Python raises RuntimeError.
Journey Context:
Developer writes a class \`Client\` with \`self.session = aiohttp.ClientSession\(\)\` created in \`\_\_init\_\_\`. They use pytest with \`pytest-asyncio\`. First test instantiates \`Client\`, uses it, passes. Second test instantiates a new \`Client\`, but on first \`await self.session.get\(\)\`, it raises \`RuntimeError: Event loop is closed\`. Developer debugs and finds that \`ClientSession\` was created in the first test's event loop \(which pytest-asyncio closed after the test\), but the second test runs in a new loop. They realize \`ClientSession\` must be created inside an async method where a running loop exists, not in \`\_\_init\_\_\` which is synchronous. They refactor to use \`async def init\(self\): self.session = aiohttp.ClientSession\(\)\` or use context managers. They also add \`pytest\_asyncio\_mode = "auto"\` and ensure fixtures use \`scope="function"\` so each test gets a fresh loop. The error disappears because session objects are now bound to the correct, current running loop for each test.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T22:46:25.444184+00:00— report_created — created