python/cpython · error · RuntimeError
Cannot exit %r without entering first
Error message
Cannot exit %r without entering first
What it means
Raised by warnings.catch_warnings.__exit__ when the context manager's __exit__ is called without a prior __enter__. The object tracks an internal _entered flag set in __enter__ and cleared in __exit__; exiting an un-entered (or already-exited and mutated) instance would corrupt the saved warning-filter state, so CPython guards it with a RuntimeError.
Source
Thrown at Lib/_py_warnings.py:729
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 sure
# that _showwarnmsg() calls _showwarnmsg_impl()
self._module.showwarning = self._module._showwarning_orig
else:
log = None
if self._filter is not None:
self._module.simplefilter(*self._filter)
return log
def __exit__(self, *exc_info):
if not self._entered:
raise RuntimeError("Cannot exit %r without entering first" % self)
with _wm._lock:
if _use_context:
self._module._warnings_context.set(self._saved_context)
else:
self._module.filters = self._filters
self._module._showwarnmsg_impl = self._showwarnmsg_impl
self._module.showwarning = self._showwarning
self._module._filters_mutated_lock_held()
class deprecated:
"""Indicate that a class, function or overload is deprecated.
When this decorator is applied to an object, the type checker
will generate a diagnostic on usage of the deprecated object.
Usage:
View on GitHub (pinned to bc6749cc3b)
Solutions
- Use the context manager form: with warnings.catch_warnings(): ... and let Python call __exit__ exactly once
- If manual control is required, call __enter__ first and guarantee __exit__ runs once (try/finally), and never reuse the instance
- Check the internal flag defensively before manual exit: if getattr(cm, '_entered', False): cm.__exit__(...)
- Use contextlib.ExitStack.enter_context(cm) instead of hand-managing enter/exit pairing
Example fix
// before
cm = warnings.catch_warnings()
cm.__exit__(None, None, None) # RuntimeError
# after
with warnings.catch_warnings():
warnings.simplefilter('ignore')
do_noisy_thing() Defensive patterns
Strategy: validation
Validate before calling
import warnings
cm = warnings.catch_warnings()
assert getattr(cm, '_entered', False) is False
cm.__enter__()
try:
warnings.simplefilter('ignore')
noisy()
finally:
if getattr(cm, '_entered', False):
cm.__exit__(None, None, None) Try / catch
try:
cm.__exit__(None, None, None)
except RuntimeError:
pass # already exited; state is consistent, safe to ignore Prevention
- Always use 'with warnings.catch_warnings():' instead of manual enter/exit
- Never reuse one catch_warnings instance for nested or repeated suppression
- Prefer contextlib.ExitStack for dynamic nesting
When it happens
Trigger: Calling cm = warnings.catch_warnings(); cm.__exit__(None, None, None) directly; manually invoking __enter__/__exit__ (e.g. to emulate a context manager across function boundaries) and calling __exit__ twice; passing a catch_warnings instance to contextlib.ExitStack and popping its callback twice.
Common situations: Code that wraps catch_warnings in a custom try/finally instead of a with block; reusing one catch_warnings instance for nested suppression; refactoring away from 'with' while keeping explicit enter/exit calls; test fixtures that conditionally enter the context.
Related errors
- {name!r} was slated for removal after Python {remove_formatt
- Cannot enter %r twice
- Expected an object of type str for 'message', not {type(mess
- {cls.__name__}() takes no arguments
- @deprecated decorator with non-None category must be applied
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/58dd3e919fddbc2e.
Report an issue: GitHub.