pytest-dev/pytest · error · RuntimeError

Cannot exit {self!r} without entering first

Error message

Cannot exit {self!r} without entering first

What it means

WarningsRecorder.__exit__ raises RuntimeError if called on an instance that was not entered first. The recorder tracks entered state and rejects unbalanced exit.

Source

Thrown at src/_pytest/recwarn.py:255

        if self._entered:
            __tracebackhide__ = True
            raise RuntimeError(f"Cannot enter {self!r} twice")
        _list = super().__enter__()
        # record=True means it's None.
        assert _list is not None
        self._list = _list
        warnings.simplefilter("always")
        return self

    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None:
        if not self._entered:
            __tracebackhide__ = True
            raise RuntimeError(f"Cannot exit {self!r} without entering first")

        super().__exit__(exc_type, exc_val, exc_tb)

        # Built-in catch_warnings does not reset entered state so we do it
        # manually here for this context manager to become reusable.
        self._entered = False


@final
class WarningsChecker(WarningsRecorder):
    def __init__(
        self,
        expected_warning: type[Warning] | tuple[type[Warning], ...] = Warning,
        match_expr: str | re.Pattern[str] | None = None,
        *,
        _ispytest: bool = False,
    ) -> None:
        check_ispytest(_ispytest)

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Always use the `with` statement so enter/exit are balanced automatically.
  2. If managing enter/exit manually, guard exit with a check of the entered state.
  3. Ensure __enter__ succeeds before any code path can reach __exit__.

Example fix

// before
recorder.__exit__(None, None, None)  # never entered
// after
with recorder:
    ...
Defensive patterns

Strategy: validation

Validate before calling

if not getattr(recorder, '_entered', False):
    raise RuntimeError('recorder not entered; cannot exit')
recorder.__exit__(None, None, None)

Prevention

When it happens

Trigger: Manually calling recorder.__exit__(...) without a prior __enter__, or a code path that exits twice (the second after state was reset). Hits recwarn.py:255.

Common situations: Direct manipulation of the context-manager protocol; a cleanup/finally block that exits a recorder that was never entered due to an earlier error.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/6ca40e4edafdd9a4.json. Report an issue: GitHub.