{"record":{"id":"ea0c21a54548e9d0","repo":"pytest-dev/pytest","slug":"cannot-enter-self-r-twice","errorCode":null,"errorMessage":"Cannot enter {self!r} twice","messagePattern":"Cannot enter (.+?) twice","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/recwarn.py","lineNumber":239,"sourceCode":"                best_idx is None\n                or not issubclass(w.category, self._list[best_idx].category)\n            ):\n                best_idx = i\n        if best_idx is not None:\n            return self._list.pop(best_idx)\n        __tracebackhide__ = True\n        raise AssertionError(f\"{cls!r} not found in warning list\")\n\n    def clear(self) -> None:\n        \"\"\"Clear the list of recorded warnings.\"\"\"\n        self._list[:] = []\n\n    # Type ignored because we basically want the `catch_warnings` generic type\n    # parameter to be ourselves but that is not possible(?).\n    def __enter__(self) -> Self:  # type: ignore[override]\n        if self._entered:\n            __tracebackhide__ = True\n            raise RuntimeError(f\"Cannot enter {self!r} twice\")\n        _list = super().__enter__()\n        # record=True means it's None.\n        assert _list is not None\n        self._list = _list\n        warnings.simplefilter(\"always\")\n        return self\n\n    def __exit__(\n        self,\n        exc_type: type[BaseException] | None,\n        exc_val: BaseException | None,\n        exc_tb: TracebackType | None,\n    ) -> None:\n        if not self._entered:\n            __tracebackhide__ = True\n            raise RuntimeError(f\"Cannot exit {self!r} without entering first\")\n\n        super().__exit__(exc_type, exc_val, exc_tb)","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/recwarn.py#L221-L257","documentation":"Raised by WarningsRecorder.__enter__ when the context manager is entered a second time without an intervening __exit__. The recorder tracks an _entered flag (reset to False on exit) to mirror correct context-manager lifecycle; double-entry would corrupt the recorded list and the warnings filter state. The RuntimeError protects against misuse such as manual re-entry.","triggerScenarios":"Calling recorder.__enter__() twice; a with-block that re-enters the same recorder via __enter__ inside the body; using a recorder in a custom harness that calls __enter__ explicitly then `with recorder:` again.","commonSituations":"Wrapping WarningsRecorder in a custom context manager that forwards __enter__ twice; fixtures that cache and re-enter a recorder across tests; misuse by internal tooling.","solutions":["Always pair __enter__ with __exit__; use the with statement so Python manages lifecycle.","Create a fresh WarningsRecorder per use rather than reusing one.","If reusing programmatically, assert `not recorder._entered` before calling __enter__."],"exampleFix":"// before\nrecorder = WarningsRecorder(_ispytest=True)\nrecorder.__enter__()\nrecorder.__enter__()  # RuntimeError\n// after\nwith WarningsRecorder(_ispytest=True) as recorder:\n    ...\n// for reuse across tests, create a new instance each time","handlingStrategy":"validation","validationCode":"assert not recorder._entered, f'cannot re-enter {recorder!r}; create a fresh recorder'","typeGuard":"def recorder_enterable(recorder) -> bool:\n    return not getattr(recorder, '_entered', False)","tryCatchPattern":null,"preventionTips":["Always use the with statement for WarningsRecorder so __enter__/__exit__ stay paired.","Do not cache and re-enter a recorder across tests; create a new instance each time.","In custom harnesses, assert not _entered before calling __enter__."],"tags":["pytest","warns","warningsrecorder","context-manager","lifecycle"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}