{"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/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/runner.py#L563-L594","documentation":"Raised as a BaseExceptionGroup by SetupState.teardown_exact when more than one exception is collected while popping and running finalizers from the fixture/test stack at the end of a test. pytest groups the per-node teardown failures into a single exception group so teardown errors from sibling fixtures are not silently lost. Each subgroup's message is 'errors while tearing down <node>'.","triggerScenarios":"Two or more fixture finalizers (yield fixtures' post-yield code, addfinalizer callbacks, autouse fixture teardowns) raise during teardown of the same test item, or finalizers across different nodes in the stack all fail. TEST_OUTCOME exceptions (AssertionError, Exception, Skip, etc.) are captured and bundled here.","commonSituations":"A fixture's cleanup hits an assertion, while a dependent fixture also fails to close a resource; switching from a passing to a failing test where multiple teardowns now misbehave; plugin finalizers interacting with broken state left by the failing test body.","solutions":["Inspect the ExceptionGroup's sub-exceptions (use `except*` on Python 3.11+, or `e.exceptions`) to identify each root cause individually.","Make each fixture teardown defensive: wrap cleanup bodies in try/except so one failing finalizer cannot mask others or cascade.","Reproduce teardown in isolation by running only the failing test with `-p no:randomly` and `--setup-show` to see fixture order.","Ensure resource handles (files, sockets, subprocesses) are closed in finally blocks rather than bare yield fixtures."],"exampleFix":"// before\n@pytest.fixture\ndef db():\n    conn = open_conn()\n    yield conn\n    conn.close()  # raises if conn is broken, masks other teardown errors\n\n// after\n@pytest.fixture\ndef db():\n    conn = open_conn()\n    try:\n        yield conn\n    finally:\n        try:\n            conn.close()\n        except Exception:\n            pass  # log and continue; let other finalizers run","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"# Python 3.11+\ntry:\n    run_test(item)\nexcept* Exception as eg:\n    for e in eg.exceptions:\n        log_teardown_failure(e)\n\n# Python < 3.11\ntry:\n    run_test(item)\nexcept BaseExceptionGroup as eg:\n    for e in eg.exceptions:\n        log_teardown_failure(e)","preventionTips":["Wrap each fixture's post-yield cleanup in try/finally so one failure cannot cascade.","Use addfinalizer or yield fixtures consistently; mixing styles complicates teardown order.","Run with --setup-show during development to visualize teardown order and catch leaks early."],"tags":["teardown","fixtures","exceptiongroup","pytest-runner"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}