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.
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)