← Debugging Guides

阅读中文版本

Python — RuntimeError: event loop is already running

Resolve "loop already running" errors when nesting asyncio run calls or calling async code from a synchronous context.

intermediatedebuggingpythonasyncio

Symptoms

  • RuntimeError: This event loop is already running or asyncio.run() cannot be called from a running event loop
  • The error appears inside a Jupyter notebook or an async web framework handler
  • Calling asyncio.run inside an async function triggers it
  • A library that starts its own loop conflicts with the app loop

Possible causes

  • asyncio.run is called from code that already runs inside a loop, such as a notebook cell or async handler
  • A synchronous wrapper starts a second loop while one is active
  • loop.run_until_complete is used on an already running loop
  • A framework manages the loop and the code tries to manage another

Diagnosis steps

Find where a loop is started

grep -rn "asyncio.run\|run_until_complete\|new_event_loop" .

Interpretation

Each hit is a candidate. Nesting any of these inside an async context raises the error.

In a notebook or async app, await instead of run

await some_coroutine()

Interpretation

When a loop already runs, use await or create a task instead of starting a new loop.

Offload sync call sites with a thread

await asyncio.to_thread(sync_fn, args)

Interpretation

If sync code must call async code, running it in a worker thread with its own loop avoids nesting on the active loop.

Root cause

Two event loops conflict. asyncio.run creates a new loop and cannot be called while another loop is running in the same thread, so nesting loop creation is the defect.

Fix

Inside async code, await coroutines directly. From synchronous code, start the loop once at the top level or run blocking work in a separate thread where a dedicated loop is acceptable.

Verify the fix

Run the code path again and confirm no RuntimeError, then confirm the coroutine actually completes by checking its side effects or return value.

Symptom walkthrough

Code that calls asyncio.run crashes with RuntimeError: asyncio.run() cannot be called from a running event loop, or This event loop is already running. The failure is common in notebooks, async web handlers and frameworks that manage their own loop, because the surrounding environment already runs a loop in the same thread.

Fix in practice

Do not create a second loop where one is running. In async code, await the coroutine or schedule a task. In synchronous code, either run the loop once at the entry point or move the work to a separate thread with its own loop. Libraries that insist on starting a loop should be called from a sync context or wrapped accordingly.

Verification

Re-run the path and confirm it completes without the RuntimeError, then check the coroutine side effects or returned value to be sure it truly ran rather than being silently skipped.

Diagnostic commands

Check the behavior with commands like these:

grep -rn "asyncio.run\|run_until_complete\|new_event_loop" .
await some_coroutine()
await asyncio.to_thread(sync_fn, args)