pytest-dev/pytest · error · BaseExceptionGroup

errors during test teardown

Error message

errors during test teardown

What it means

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.

Solutions

  1. Inspect the BaseExceptionGroup's .exceptions list to see each teardown failure individually.
  2. Make each finalizer defensive (try/except inside, log and continue) so one failure does not mask others.
  3. Fix the root-cause finalizer first; re-run to confirm remaining failures clear.
  4. Use pytest --tb=short or -rA to render every teardown error in the summary.

Example fix

// before
@pytest.fixture
def conn():
    c = open_conn()
    yield c
    c.close()  # raises if conn never opened
// after
@pytest.fixture
def conn():
    c = open_conn()
    try:
        yield c
    finally:
        try:
            c.close()
        except Exception:
            logger.exception('teardown close failed')
Defensive patterns

Strategy: try-catch

Validate before calling

import contextlib, traceback
# pattern for finalizers: never let one mask another
def safe_finalizer(fn, *a, **k):
    try:
        return fn(*a, **k)
    except Exception:
        traceback.print_exc()
        return None

Try / catch

@pytest.fixture
def resource():
    r = open_resource()
    try:
        yield r
    finally:
        try:
            r.close()
        except Exception:
            logger.exception('resource.close failed during teardown')

Prevention

When it happens

Trigger: 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'.

Common situations: 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.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/1bf611b3124e735a. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/runner.py:581

            node, (finalizers, _) = self.stack.popitem()
            these_exceptions = []
            while finalizers:
                fin = finalizers.pop()
                try:
                    fin()
                except TEST_OUTCOME as e:
                    these_exceptions.append(e)

            if len(these_exceptions) == 1:
                exceptions.extend(these_exceptions)
            elif these_exceptions:
                msg = f"errors while tearing down {node!r}"
                exceptions.append(BaseExceptionGroup(msg, these_exceptions[::-1]))

        if len(exceptions) == 1:
            raise exceptions[0]
        elif exceptions:
            raise BaseExceptionGroup("errors during test teardown", exceptions[::-1])
        if nextitem is None:
            assert not self.stack


def collect_one_node(collector: Collector) -> CollectReport:
    ihook = collector.ihook
    ihook.pytest_collectstart(collector=collector)
    rep: CollectReport = ihook.pytest_make_collect_report(collector=collector)
    call = rep.__dict__.pop("call", None)
    if call and check_interactive_exception(call, rep):
        ihook.pytest_exception_interact(node=collector, call=call, report=rep)
    return rep

View on GitHub (pinned to 0d6fbdeffa)