python/cpython · error · RuntimeError
Cannot enter %r twice
Error message
Cannot enter %r twice
What it means
Raised by catch_warnings.__enter__ when a single catch_warnings instance is used as a context manager more than once. The object saves the previous filter state/hook on entry and restores it on exit, so re-entering would overwrite the first saved state and corrupt restoration; an _entered flag therefore makes the second entry fail with RuntimeError('Cannot enter %r twice').
Source
Thrown at Lib/_py_warnings.py:700
self._module = sys.modules['warnings'] if module is None else module
self._entered = False
if action is None:
self._filter = None
else:
self._filter = (action, category, lineno, append)
def __repr__(self):
args = []
if self._record:
args.append("record=True")
if self._module is not sys.modules['warnings']:
args.append("module=%r" % self._module)
name = type(self).__name__
return "%s(%s)" % (name, ", ".join(args))
def __enter__(self):
if self._entered:
raise RuntimeError("Cannot enter %r twice" % self)
self._entered = True
with _wm._lock:
if _use_context:
self._saved_context, context = self._module._new_context()
else:
context = None
self._filters = self._module.filters
self._module.filters = self._filters[:]
self._showwarnmsg_impl = self._module._showwarnmsg_impl
self._showwarning = self._module.showwarning
self._module._filters_mutated_lock_held()
if self._record:
if _use_context:
context.log = log = []
else:
log = []
self._module._showwarnmsg_impl = log.append
# Reset showwarning() to the default implementation to make sureView on GitHub (pinned to bc6749cc3b)
Solutions
- Create a fresh instance for each use: `with warnings.catch_warnings(record=True) as w:` inline
- Make fixtures function-scoped so every test gets a new catch_warnings
- If you need the object ahead of time, instantiate it right before the with statement
- Never store catch_warnings on long-lived objects (class attributes, module globals)
Example fix
# before
_caught = warnings.catch_warnings(record=True)
with _caught as w:
...
with _caught as w: # RuntimeError: Cannot enter ... twice
...
# after
with warnings.catch_warnings(record=True) as w:
...
with warnings.catch_warnings(record=True) as w:
... Defensive patterns
Strategy: validation
Validate before calling
import warnings
def fresh_catch(record=True):
"""Always returns a never-entered catch_warnings."""
return warnings.catch_warnings(record=record)
# use a new one per block:
with fresh_catch() as w:
... Type guard
def is_enterable(cw) -> bool:
return not getattr(cw, '_entered', False) Try / catch
try:
with cw:
...
except RuntimeError as e:
if 'Cannot enter' in str(e):
with warnings.catch_warnings(record=cw._record) as w: # start fresh
...
else:
raise Prevention
- Construct catch_warnings inline in the with statement; don't hoist it to attributes or globals
- Scope pytest fixtures that wrap catch_warnings to function level, never session/module
- If a helper returns a context manager, have it build a new instance per call
When it happens
Trigger: cw = warnings.catch_warnings(record=True) created once (e.g. on a test class or module) and reused across two `with cw:` blocks; a helper fixture returning a cached catch_warnings; storing the instance on self and entering it in multiple methods.
Common situations: pytest fixtures that instantiate catch_warnings at module scope instead of per-test; refactoring a `with` block into two blocks while keeping the shared object; recursive code paths that each try to enter the same saved context manager.
Related errors
- Cannot exit %r without entering first
- Object type mismatch in limited API annotation for {name}: {
- warnings.showwarning() must be set to a function or method
- invalid action: {action!r}
- message must be a string
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/8af0de8cacb27528.
Report an issue: GitHub.