pytest ScopeMismatch: function scoped fixture (tested)
ScopeMismatch: You tried to access the function scoped fixture X with a session scoped request object means a wider-scoped fixture depends on a narrower one. Widen the dependency's scope, narrow the consumer, or use tmp_path_factory / pytest.MonkeyPatch.context() for the built-ins.
A fixture can only use fixtures with the same or wider scope (function < class < module < package < session). A session fixture is created once, so it cannot depend on something that is recreated for every test. Measured on pytest 9.1.1.
1. A session fixture using your function-scoped fixture
$ cat test_a.py
import pytest
@pytest.fixture
def db_url():
return "sqlite://"
@pytest.fixture(scope="session")
def engine(db_url):
return {"url": db_url}
def test_x(engine):
assert engine
$ pytest -q -p no:cacheprovider | grep -E "^ScopeMismatch|^ERROR"
ScopeMismatch: You tried to access the function scoped fixture db_url with a session scoped request object. Requesting fixture stack:
ERROR test_a.py::test_x - Failed: ScopeMismatch: You tried to access the func...
The error names the narrower fixture (db_url, function scope) and the scope that asked for it (session). The test is reported as ERROR at setup.
Fix: widen the dependency (or narrow the consumer)
$ cat test_b.py
import pytest
@pytest.fixture(scope="session")
def db_url():
return "sqlite://"
@pytest.fixture(scope="session")
def engine(db_url):
return {"url": db_url}
@pytest.fixture(scope="session")
def data_dir(tmp_path_factory):
return tmp_path_factory.mktemp("data")
def test_x(engine, data_dir):
assert engine and data_dir.exists()
$ pytest -q -p no:cacheprovider | tail -1
1 passed in 0.00s
Give db_url session scope too, or make engine function-scoped if it is cheap. For temporary directories in session fixtures use tmp_path_factory.mktemp(), the session-scoped counterpart of tmp_path, as data_dir does here.
2. Built-in fixtures: tmp_path and monkeypatch are function-scoped
$ cat test_c.py
import pytest
@pytest.fixture(scope="session")
def data_dir(tmp_path):
return tmp_path
@pytest.fixture(scope="module")
def patched(monkeypatch):
monkeypatch.setenv("X", "1")
def test_x(data_dir):
pass
def test_y(patched):
pass
$ pytest -q -p no:cacheprovider | grep -E "^ScopeMismatch"
ScopeMismatch: You tried to access the function scoped fixture tmp_path with a session scoped request object. Requesting fixture stack:
ScopeMismatch: You tried to access the function scoped fixture monkeypatch with a module scoped request object. Requesting fixture stack:
tmp_path, tmpdir, monkeypatch, capsys and caplog are function-scoped, so a module or session fixture cannot request them. For monkeypatch, use pytest.MonkeyPatch.context() inside the wider fixture; changes are undone when the fixture finishes (here, at the end of the module):
$ cat test_c.py
import os, pytest
@pytest.fixture(scope="module")
def patched():
with pytest.MonkeyPatch.context() as mp:
mp.setenv("X", "1")
yield
def test_y(patched):
assert os.environ["X"] == "1"
$ pytest -q -p no:cacheprovider | tail -1
1 passed in 0.00s
Related: pytest fixture not found, pytest ERROR at setup.
Frequently asked questions
What causes pytest ScopeMismatch?
A fixture with module or session scope requests a fixture with a narrower scope, usually function scope (the default).
How do I use tmp_path in a session fixture?
You cannot; use tmp_path_factory.mktemp('name'), which is session-scoped.
How do I use monkeypatch in a module-scoped fixture?
Use with pytest.MonkeyPatch.context() as mp: inside the fixture and yield; changes are undone when the fixture is torn down.
Written with AI assistance. Measured on 2026-10-23 with pytest 9.1.1 on Python 3.13.5 in a clean virtualenv. Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python and pytest are free.