python/cpython · error · TypeError
loop must be an instance of AbstractEventLoop or None, not '
Error message
loop must be an instance of AbstractEventLoop or None, not '{type(loop).__name__}' What it means
asyncio.set_event_loop() validates its argument: it must be an AbstractEventLoop instance or None. Passing anything else (a factory, a coroutine, a mock, a loop policy) raises this TypeError immediately, guarding the thread-local loop slot from corrupt state.
Source
Thrown at Lib/asyncio/events.py:755
If there is no running event loop set, the function will return
the loop set by ``set_event_loop()``, or raise a RuntimeError if
no loop has been set.
"""
# NOTE: this function is implemented in C (see _asynciomodule.c)
current_loop = _get_running_loop()
if current_loop is not None:
return current_loop
return _get_event_loop()
def set_event_loop(loop):
"""Set the event loop for the current thread to loop.
If loop is None, the current event loop is unset.
"""
if loop is not None and not isinstance(loop, AbstractEventLoop):
raise TypeError(f"loop must be an instance of AbstractEventLoop or None, not '{type(loop).__name__}'")
_local._loop = loop
def new_event_loop():
"""Create and return a new event loop object."""
if sys.platform == 'win32':
from .windows_events import EventLoop
else:
from .unix_events import EventLoop
return EventLoop()
# Alias pure-Python implementations for testing purposes.
_py__get_running_loop = _get_running_loop
_py__set_running_loop = _set_running_loop
_py_get_running_loop = get_running_loop
_py_get_event_loop = get_event_loop
View on GitHub (pinned to bc6749cc3b)
Solutions
- Instantiate the loop: asyncio.set_event_loop(asyncio.new_event_loop())
- To clear the thread's loop, pass None explicitly
- In tests, use unittest.mock patches with spec, or pytest-asyncio fixtures instead of manual set_event_loop
Example fix
# before asyncio.set_event_loop(asyncio.new_event_loop) # passed the function # after asyncio.set_event_loop(asyncio.new_event_loop()) # passed an instance
Defensive patterns
Strategy: type-guard
Validate before calling
import asyncio assert isinstance(loop, (asyncio.AbstractEventLoop, type(None)))
Type guard
def is_loop_or_none(obj) -> bool:
return obj is None or isinstance(obj, asyncio.AbstractEventLoop) Prevention
- Always pass new_event_loop() result, not the function
- Lint for set_event_loop(asyncio.new_event_loop) (missing parens)
- Use spec-ed mocks in tests touching loop APIs
When it happens
Trigger: Calling set_event_loop(new_event_loop) with missing parentheses, passing the EventLoop class instead of an instance, passing a concurrent.futures executor, or a Mock object in tests without spec.
Common situations: Typos in test setup; copying example code that stored a loop factory; mocking asyncio and forgetting spec=asyncio.AbstractEventLoop; passing the result of uvloop.Loop (class) instead of uvloop.new_event_loop().
Related errors
- Not implemented
- {htmldir!r} is not a Sphinx HTML output directory
- Unknown thread safety level {level!r} for {name!r}. Valid le
- {name} is not part of stable ABI. Document it as `c:macro::`
- deprecated-removed:: second argument cannot be `next`
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/34ae83561d1d90c1.
Report an issue: GitHub.