{"record":{"id":"1bf611b3124e735a","repo":"pytest-dev/pytest","slug":"errors-during-test-teardown","errorCode":null,"errorMessage":"errors during test teardown","messagePattern":"errors during test teardown","errorType":"exception","errorClass":"BaseExceptionGroup","httpStatus":null,"severity":"error","filePath":"src/_pytest/runner.py","lineNumber":581,"sourceCode":"            node, (finalizers, _) = self.stack.popitem()\n            these_exceptions = []\n            while finalizers:\n                fin = finalizers.pop()\n                try:\n                    fin()\n                except TEST_OUTCOME as e:\n                    these_exceptions.append(e)\n\n            if len(these_exceptions) == 1:\n                exceptions.extend(these_exceptions)\n            elif these_exceptions:\n                msg = f\"errors while tearing down {node!r}\"\n                exceptions.append(BaseExceptionGroup(msg, these_exceptions[::-1]))\n\n        if len(exceptions) == 1:\n            raise exceptions[0]\n        elif exceptions:\n            raise BaseExceptionGroup(\"errors during test teardown\", exceptions[::-1])\n        if nextitem is None:\n            assert not self.stack\n\n\ndef collect_one_node(collector: Collector) -> CollectReport:\n    ihook = collector.ihook\n    ihook.pytest_collectstart(collector=collector)\n    rep: CollectReport = ihook.pytest_make_collect_report(collector=collector)\n    call = rep.__dict__.pop(\"call\", None)\n    if call and check_interactive_exception(call, rep):\n        ihook.pytest_exception_interact(node=collector, call=call, report=rep)\n    return rep\n","sourceCodeStart":563,"sourceCodeEnd":594,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/runner.py#L563-L594","documentation":"Not a raised exception object per se but the message of the BaseExceptionGroup propagated by SetupState.teardown_exact when multiple finalizers/teardowns across one or more nodes raise. Each failing finalizer is collected; if there is more than one across the whole teardown, they are bundled into a BaseExceptionGroup titled 'errors during test teardown' (a per-node group is titled 'errors while tearing down {node}'). This surfaces every teardown failure rather than just the first.","triggerScenarios":"Two or more pytest fixtures' finalizers (or teardown methods) raising during teardown_exact; a single node with multiple failing finalizers produces the 'errors while tearing down {node}' inner group, and multiple such nodes are aggregated under 'errors during test teardown'.","commonSituations":"Fixture finalizers that close resources which were never opened; teardown calling external services that are down; yield-based fixtures where the post-yield code raises; cascading failures in session/module/function scopes.","solutions":["Inspect the BaseExceptionGroup's .exceptions list to see each teardown failure individually.","Make each finalizer defensive (try/except inside, log and continue) so one failure does not mask others.","Fix the root-cause finalizer first; re-run to confirm remaining failures clear.","Use pytest --tb=short or -rA to render every teardown error in the summary."],"exampleFix":"// before\n@pytest.fixture\ndef conn():\n    c = open_conn()\n    yield c\n    c.close()  # raises if conn never opened\n// after\n@pytest.fixture\ndef conn():\n    c = open_conn()\n    try:\n        yield c\n    finally:\n        try:\n            c.close()\n        except Exception:\n            logger.exception('teardown close failed')","handlingStrategy":"try-catch","validationCode":"import contextlib, traceback\n# pattern for finalizers: never let one mask another\ndef safe_finalizer(fn, *a, **k):\n    try:\n        return fn(*a, **k)\n    except Exception:\n        traceback.print_exc()\n        return None","typeGuard":null,"tryCatchPattern":"@pytest.fixture\ndef resource():\n    r = open_resource()\n    try:\n        yield r\n    finally:\n        try:\n            r.close()\n        except Exception:\n            logger.exception('resource.close failed during teardown')","preventionTips":["Wrap each fixture's post-yield teardown in try/except so one failure does not mask others.","Inspect BaseExceptionGroup.exceptions to enumerate every teardown failure.\n        Use -rA / --tb=short to surface all teardown errors in the summary.","Order finalizers to release resources in reverse acquisition order to minimize cascading failures."],"tags":["pytest","runner","teardown","exception-group","fixtures","finalizer"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}