RustPython/RustPython · error · RuntimeError
Cannot enter %r twice
Error message
Cannot enter %r twice
What it means
warnings.catch_warnings is a one-shot context manager: __enter__ sets an internal _entered flag and raises RuntimeError if the same instance is entered again. Entering twice would save the already-swapped filter state as the 'original', making restoration impossible, so reuse is rejected outright.
Source
Thrown at Lib/_py_warnings.py:641
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._showwarning = self._module.showwarning
self._showwarnmsg_impl = self._module._showwarnmsg_impl
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 aaeab4f754)
Solutions
- Construct a fresh warnings.catch_warnings() for each with statement
- In test fixtures, create the instance inside the test or per-test setup, never once at module import
- Wrap creation in a small factory function if you need repeated enter/exit cycles
Example fix
# before
cm = warnings.catch_warnings()
with cm:
...
with cm: # RuntimeError: Cannot enter ... twice
...
# after
with warnings.catch_warnings():
...
with warnings.catch_warnings():
... Defensive patterns
Strategy: validation
Validate before calling
if getattr(cm, "_entered", False):
cm = warnings.catch_warnings() # previous use exhausted it; start fresh
with cm:
... Type guard
def is_fresh_catch_warnings(cm) -> bool:
return not getattr(cm, "_entered", False) Try / catch
try:
with cm:
...
except RuntimeError as e:
if "Cannot enter" in str(e):
with warnings.catch_warnings():
...
else:
raise Prevention
- Construct catch_warnings inline in the with statement; treat instances as single-use
- Never share one catch_warnings instance across tests, fixtures, or threads
- Nesting distinct instances is fine; re-entering the same one is not
When it happens
Trigger: cm = warnings.catch_warnings(); with cm: ... followed later by with cm: ... -- reusing a stored instance; a module-level catch_warnings object entered by two different tests.
Common situations: Test suites that create the context manager once in a fixture and enter it per test; refactoring a with-block into a helper that receives the cm object; sharing one cm across setup/teardown.
Related errors
- Cannot exit %r without entering first
- Unrecognized action (%r) in warnings.filters: %s
- {name!r} was slated for removal after Python {remove_formatt
- BUILD_GNU_TYPE is not defined
- Expected Theme object, found {t}
AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17).
Data as JSON: /api/errors/f259d6927b55a572.
Report an issue: GitHub.