{"id":"5bd26589b2af6b77","repo":"pytest-dev/pytest","slug":"errors-while-tearing-down-fixture-self-argname","errorCode":null,"errorMessage":"errors while tearing down fixture \"{self.argname}\" of {node}","messagePattern":"errors while tearing down fixture \"(.+?)\" of (.+?)","errorType":"exception","errorClass":"BaseExceptionGroup","httpStatus":null,"severity":"error","filePath":"src/_pytest/fixtures.py","lineNumber":1230,"sourceCode":"\n        exceptions: list[BaseException] = []\n        while self._finalizers:\n            fin = self._finalizers.pop()\n            try:\n                fin()\n            except BaseException as e:\n                exceptions.append(e)\n        node = request.node\n        # Even if finalization fails, we invalidate the cached fixture\n        # value and remove all finalizers because they may be bound methods\n        # which will keep instances alive.\n        self.cached_result = None\n        self._finalizers.clear()\n        if len(exceptions) == 1:\n            raise exceptions[0]\n        elif len(exceptions) > 1:\n            msg = f'errors while tearing down fixture \"{self.argname}\" of {node}'\n            raise BaseExceptionGroup(msg, exceptions[::-1])\n\n    def execute(self, request: SubRequest) -> FixtureValue:\n        \"\"\"Return the value of this fixture, executing it if not cached.\"\"\"\n        # Ensure that the dependent fixtures requested by this fixture are loaded.\n        # This needs to be done before checking if we have a cached value, since\n        # if a dependent fixture has their cache invalidated, e.g. due to\n        # parametrization, they finalize themselves and fixtures depending on it\n        # (which will likely include this fixture) setting `self.cached_result = None`.\n        # See #4871\n        requested_fixtures_that_should_finalize_us = []\n        for argname in self.argnames:\n            fixturedef = request._get_active_fixturedef(argname)\n            # Saves requested fixtures in a list so we later can add our finalizer\n            # to them, ensuring that if a requested fixture gets torn down we get torn\n            # down first. This is generally handled by SetupState, but still currently\n            # needed when this fixture is not parametrized but depends on a parametrized\n            # fixture.\n            requested_fixtures_that_should_finalize_us.append(fixturedef)","sourceCodeStart":1212,"sourceCodeEnd":1248,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/fixtures.py#L1212-L1248","documentation":"Raised by `FixtureDef.finish` when two or more finalizers/teardown steps of a single fixture raise during teardown. pytest collects all exceptions and re-raises them wrapped in a `BaseExceptionGroup` (the message names the fixture argname and the node) so no teardown error is swallowed. A single exception is re-raised unwrapped.","triggerScenarios":"A fixture whose teardown (after yield) plus one or more of its dependent finalizers both raise. Common when the post-yield cleanup raises and an `addfinalizer` callback registered elsewhere also raises.","commonSituations":"Teardown of a resource fails (connection already closed) and a second finalizer also fails. CI flakiness where cleanup hits a transient error. Migrating to Python 3.11+ where ExceptionGroup surfaces.","solutions":["Make teardown code defensive: wrap each cleanup step in try/except and log instead of raising where safe.","Use `except*` (exception groups) at the test runner level, or `pytest.raises(BaseExceptionGroup)` in tests.","Identify which finalizers failed from the message and fix the root cause of each."],"exampleFix":"// before\n@pytest.fixture\ndef db():\n    conn = connect()\n    yield conn\n    conn.close()          # may raise\n    conn.log_logout()     # also may raise -> group\n// after\n@pytest.fixture\ndef db():\n    conn = connect()\n    yield conn\n    try:\n        conn.close()\n    finally:\n        try:\n            conn.log_logout()\n        except Exception:\n            pass","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    yield resource\nexcept BaseExceptionGroup as eg:\n    for e in eg.exceptions:\n        log.warning(\"teardown error: %r\", e)","preventionTips":["Wrap each teardown step in try/except so one failure does not cascade.","Register finalizers that clean independent resources so partial failures are tolerated.","Test teardown paths explicitly to surface latent errors."],"tags":["pytest","fixtures","teardown","exceptiongroup"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}