pytest-dev/pytest · error · AttributeError

path not available in {self.scope}-scoped context

Error message

path not available in {self.scope}-scoped context

What it means

Raised by `request.path` when the request scope is not in ("function", "class", "module", "package"). Only the session scope (and beyond) lacks a concrete filesystem path, so this fires almost exclusively from session-scoped fixtures. The path returned otherwise is the file where the test was collected.

Source

Thrown at src/_pytest/fixtures.py:616

        """Instance (can be None) on which test function was collected."""
        if self.scope != "function":
            return None
        return getattr(self._pyfuncitem, "instance", None)

    @property
    def module(self):
        """Python module object where the test function was collected."""
        if self.scope not in ("function", "class", "module"):
            raise AttributeError(f"module not available in {self.scope}-scoped context")
        mod = self._pyfuncitem.getparent(_pytest.python.Module)
        assert mod is not None
        return mod.obj

    @property
    def path(self) -> Path:
        """Path where the test function was collected."""
        if self.scope not in ("function", "class", "module", "package"):
            raise AttributeError(f"path not available in {self.scope}-scoped context")
        return self._pyfuncitem.path

    @property
    def keywords(self) -> MutableMapping[str, Any]:
        """Keywords/markers dictionary for the underlying node."""
        node: nodes.Node = self.node
        return node.keywords

    @property
    def session(self) -> Session:
        """Pytest session object."""
        return self._pyfuncitem.session

    @abc.abstractmethod
    def addfinalizer(self, finalizer: Callable[[], object]) -> None:
        """Add finalizer/teardown function to be called without arguments after
        the last test within the requesting test context finished execution."""
        raise NotImplementedError()

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Use `request.config.rootpath` for repo-root-relative resolution in session scope.
  2. Derive the path from a collected node via `request.session` items, or pass it in from a narrower fixture.
  3. Keep the fixture at module/package scope if a per-file path is required.

Example fix

// before
@pytest.fixture(scope="session")
def base(request):
    return request.path  # AttributeError
// after
@pytest.fixture(scope="session")
def base(request):
    return request.config.rootpath
Defensive patterns

Strategy: validation

Validate before calling

if request.scope in ("function", "class", "module", "package"):
    p = request.path
else:
    p = request.config.rootpath  # session scope

Type guard

def can_access_path(request) -> bool:
    return getattr(request, "scope", None) in ("function", "class", "module", "package")

Try / catch

try:
    p = request.path
except AttributeError:
    p = request.config.rootpath

Prevention

When it happens

Trigger: Calling `request.path` inside a fixture with `scope="session"`. e.g. `@pytest.fixture(scope="session")\ndef repo_root(request):\n return request.path.parent.parent`.

Common situations: A session-scoped fixture in conftest.py trying to derive paths relative to the test file. Refactoring a function-scoped path-based fixture to session scope.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/98e1b970a68f6922.json. Report an issue: GitHub.