pytest-dev/pytest · error · ValueError

did not yield a value

Error message

{request.fixturename} did not yield a value

What it means

At fixtures.py:1061 a generator-based fixture (one using 'yield') raised StopIteration on the first next() call, meaning the function executed without reaching any 'yield' statement. pytest wraps this as ValueError('{fixturename} did not yield a value') so teardown is not registered on an empty generator. The fixture must always reach a yield when written in generator style.

Solutions

  1. Ensure every code path through the fixture reaches the 'yield' statement.
  2. Move guard logic so the yield still executes (yield a sentinel/default value if needed) instead of returning early.
  3. If conditional teardown is needed, yield first then branch on teardown logic after yield.
  4. Use a non-generator fixture (plain return) if no teardown is required.

Example fix

// before
@pytest.fixture
def client():
    if not ENABLED:
        return  # skips yield -> error
    c = make_client()
    yield c
    c.close()
// after
@pytest.fixture
def client():
    if not ENABLED:
        yield None
        return
    c = make_client()
    yield c
    c.close()
Defensive patterns

Strategy: validation

Validate before calling

# Static check: ensure every @pytest.fixture with 'yield' reaches it on all paths.
# Use AST scan in a pre-commit hook.
import ast, pathlib
for f in pathlib.Path('tests').rglob('test_*.py'):
    tree = ast.parse(f.read_text())
    # naive: flag any fixture func with 'return' before 'yield' (use a linter rule)

Prevention

When it happens

Trigger: A fixture decorated with @pytest.fixture whose body uses 'yield' but a conditional branch returns or raises before the yield; a 'yield' inside an if/for block that is skipped; early 'return' before yield in a generator fixture.

Common situations: Guard clauses (if not enabled: return) in a yield-fixture that skip the yield; refactoring a return-style fixture to yield-style but missing the yield on some path; skip/pytest.exit calls before yield.

Related errors


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

Appendix: source

Thrown at src/_pytest/fixtures.py:1061

            for line in lines[1:]:
                tw.line(
                    f"{ExceptionInfoFormatter.flow_marker}       {line.strip()}",
                    red=True,
                )
        tw.line()
        tw.line(f"{os.fspath(self.filename)}:{self.firstlineno + 1}")


def call_fixture_func(
    fixturefunc: _FixtureFunc[FixtureValue], request: FixtureRequest, kwargs
) -> FixtureValue:
    if inspect.isgeneratorfunction(fixturefunc):
        fixturefunc = cast(Callable[..., Generator[FixtureValue]], fixturefunc)
        generator = fixturefunc(**kwargs)
        try:
            fixture_result = next(generator)
        except StopIteration:
            raise ValueError(f"{request.fixturename} did not yield a value") from None
        finalizer = functools.partial(_teardown_yield_fixture, fixturefunc, generator)
        request.addfinalizer(finalizer)
    else:
        fixturefunc = cast(Callable[..., FixtureValue], fixturefunc)
        fixture_result = fixturefunc(**kwargs)
    return fixture_result


def _teardown_yield_fixture(fixturefunc, it) -> None:
    """Execute the teardown of a fixture function by advancing the iterator
    after the yield and ensure the iteration ends (if not it means there is
    more than one yield in the function)."""
    try:
        next(it)
    except StopIteration:
        pass
    else:
        fs, lineno = getfslineno(fixturefunc)

View on GitHub (pinned to 0d6fbdeffa)