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
- Ensure every code path through the fixture reaches the 'yield' statement.
- Move guard logic so the yield still executes (yield a sentinel/default value if needed) instead of returning early.
- If conditional teardown is needed, yield first then branch on teardown logic after yield.
- 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
- Always place 'yield' as the last statement before teardown, after all guards.
- Prefer plain-return fixtures when no teardown is needed.
- Use a linter (flake8-pytest-style) to enforce fixture shape.
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
- class fixtures not supported (maybe in the future)
- Error evaluating while defining fixture ' '. Expected a…
- errors during test teardown
- errors while tearing down fixture
- import error in
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)