{"record":{"id":"8af0de8cacb27528","repo":"python/cpython","slug":"cannot-enter-r-twice","errorCode":null,"errorMessage":"Cannot enter %r twice","messagePattern":"Cannot enter %r twice","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Lib/_py_warnings.py","lineNumber":700,"sourceCode":"        self._module = sys.modules['warnings'] if module is None else module\n        self._entered = False\n        if action is None:\n            self._filter = None\n        else:\n            self._filter = (action, category, lineno, append)\n\n    def __repr__(self):\n        args = []\n        if self._record:\n            args.append(\"record=True\")\n        if self._module is not sys.modules['warnings']:\n            args.append(\"module=%r\" % self._module)\n        name = type(self).__name__\n        return \"%s(%s)\" % (name, \", \".join(args))\n\n    def __enter__(self):\n        if self._entered:\n            raise RuntimeError(\"Cannot enter %r twice\" % self)\n        self._entered = True\n        with _wm._lock:\n            if _use_context:\n                self._saved_context, context = self._module._new_context()\n            else:\n                context = None\n                self._filters = self._module.filters\n                self._module.filters = self._filters[:]\n                self._showwarnmsg_impl = self._module._showwarnmsg_impl\n            self._showwarning = self._module.showwarning\n            self._module._filters_mutated_lock_held()\n            if self._record:\n                if _use_context:\n                    context.log = log = []\n                else:\n                    log = []\n                    self._module._showwarnmsg_impl = log.append\n                # Reset showwarning() to the default implementation to make sure","sourceCodeStart":682,"sourceCodeEnd":718,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_py_warnings.py#L682-L718","documentation":"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').","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"# before\n_caught = warnings.catch_warnings(record=True)\nwith _caught as w:\n    ...\nwith _caught as w:      # RuntimeError: Cannot enter ... twice\n    ...\n\n# after\nwith warnings.catch_warnings(record=True) as w:\n    ...\nwith warnings.catch_warnings(record=True) as w:\n    ...","handlingStrategy":"validation","validationCode":"import warnings\n\ndef fresh_catch(record=True):\n    \"\"\"Always returns a never-entered catch_warnings.\"\"\"\n    return warnings.catch_warnings(record=record)\n\n# use a new one per block:\nwith fresh_catch() as w:\n    ...","typeGuard":"def is_enterable(cw) -> bool:\n    return not getattr(cw, '_entered', False)","tryCatchPattern":"try:\n    with cw:\n        ...\nexcept RuntimeError as e:\n    if 'Cannot enter' in str(e):\n        with warnings.catch_warnings(record=cw._record) as w:  # start fresh\n            ...\n    else:\n        raise","preventionTips":["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"],"tags":["warnings","context-manager","state","testing"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}