Skip to content
Latchkey

Python "asyncio.run() cannot be called from a running event loop" in CI

asyncio.run() creates and owns a fresh event loop; it cannot be called when one is already running. Calling it inside an async test or an already-async context raises this RuntimeError.

What this error means

A test fails with "RuntimeError: asyncio.run() cannot be called from a running event loop," typically when an async test body calls asyncio.run(...) on a coroutine.

pytest
RuntimeError: asyncio.run() cannot be called from a running event loop
sys:1: RuntimeWarning: coroutine 'fetch' was never awaited

Common causes

asyncio.run() nested inside a running loop

An async test (or async framework handler) is already inside a loop, so a fresh asyncio.run() cannot start another.

Wrapping awaitables instead of awaiting them

Calling asyncio.run(coro()) where a plain await coro() was intended re-enters the loop.

How to fix it

Await directly in async tests

  1. Mark the test async and use pytest-asyncio.
  2. Replace asyncio.run(coro()) with await coro().
  3. Re-run.
Python
import pytest

@pytest.mark.asyncio
async def test_fetch():
    result = await fetch()      # not asyncio.run(fetch())
    assert result.ok

Run blocking async code off the loop when needed

If you truly must drive a coroutine from sync code already inside a loop, offload it to another thread.

Python
import asyncio
result = asyncio.run_coroutine_threadsafe(coro(), loop).result()

How to prevent it

  • Use await inside async contexts; reserve asyncio.run() for the top-level entry point.
  • Adopt pytest-asyncio for async tests rather than manual loop management.
  • Avoid wrapping coroutines in asyncio.run() deep in a call stack.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →