pytest-asyncio "RuntimeError: Event loop is closed" in CI
Async code tried to schedule work on an event loop that pytest-asyncio had already closed. This happens when a fixture or resource outlives the loop it was created on, or when loop scope and fixture scope disagree.
What this error means
An async test or its teardown fails with "RuntimeError: Event loop is closed", sometimes only on teardown of a session/module-scoped async fixture.
RuntimeError: Event loop is closed
... during teardown of <async fixture 'client'>Common causes
A resource outlives its event loop
An async client/connection created on a function-scoped loop is used or closed after that loop is gone.
Loop scope and fixture scope mismatch
A session-scoped async fixture with a function-scoped loop (or vice versa) ends up touching a closed loop.
How to fix it
Align async fixture and loop scope
Set a consistent loop scope so async fixtures and the loop share a lifetime.
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"Create and close resources within the same loop
Construct async clients inside the test (or a same-scope fixture) so they live and die on one loop.
@pytest_asyncio.fixture
async def client():
async with httpx.AsyncClient() as c:
yield cHow to prevent it
- Keep async fixture scope and loop scope consistent.
- Open and close async resources on the same loop.
- Pin pytest-asyncio and set its loop-scope config explicitly.