pytest-dev/pytest · error · ValueError
{self} is the upper-most scope
Error message
{self} is the upper-most scope What it means
Mirror of the lower-most check: Scope.next_higher() walks one step up the Function < Class < Module < Package < Session chain. Session is the highest member (last index), so next_higher() on it has no target and raises ValueError. Like its sibling, this guards internal scope-walking logic and indicates a programming error, not a user configuration problem.
Source
Thrown at src/_pytest/scope.py:53
# Scopes need to be listed from lower to higher.
Function = "function"
Class = "class"
Module = "module"
Package = "package"
Session = "session"
def next_lower(self) -> Scope:
"""Return the next lower scope."""
index = _SCOPE_INDICES[self]
if index == 0:
raise ValueError(f"{self} is the lower-most scope")
return _ALL_SCOPES[index - 1]
def next_higher(self) -> Scope:
"""Return the next higher scope."""
index = _SCOPE_INDICES[self]
if index == len(_SCOPE_INDICES) - 1:
raise ValueError(f"{self} is the upper-most scope")
return _ALL_SCOPES[index + 1]
def __lt__(self, other: Scope) -> bool:
self_index = _SCOPE_INDICES[self]
other_index = _SCOPE_INDICES[other]
return self_index < other_index
@classmethod
def from_user(
cls, scope_name: ScopeName, descr: str, where: str | None = None
) -> Scope:
"""
Given a scope name from the user, return the equivalent Scope enum. Should be used
whenever we want to convert a user provided scope name to its enum object.
If the scope name is invalid, construct a user friendly message and call pytest.fail.
"""
from _pytest.outcomes import failView on GitHub (pinned to 0d6fbdeffa)
Solutions
- Guard the call: check `scope is not Scope.Session` before invoking next_higher().
- Use `index < len(_SCOPE_INDICES) - 1` as the bound, mirroring the source check at scope.py:52.
- Prefer iterating _ALL_SCOPES explicitly with a bounded loop rather than relying on next_higher() to stop.
Example fix
# before
higher = scope.next_higher()
# after
if scope is Scope.Session:
higher = None
else:
higher = scope.next_higher() Defensive patterns
Strategy: validation
Validate before calling
from _pytest.scope import Scope, _ALL_SCOPES, _SCOPE_INDICES
def safe_next_higher(scope: Scope):
if scope is _ALL_SCOPES[-1]:
return None
return scope.next_higher() Type guard
from _pytest.scope import Scope, _ALL_SCOPES
def has_higher_scope(scope: Scope) -> bool:
"""True when next_higher() is safe to call."""
return scope is not _ALL_SCOPES[-1] Try / catch
try:
higher = scope.next_higher()
except ValueError:
# scope is Session; nothing above it
higher = None Prevention
- Treat next_higher() as partial: check against Session (the last scope) first.
- Use the index-based bound `index < len(_SCOPE_INDICES) - 1` exactly as the source does.
- Document scope-walking helpers as partial functions so callers know to handle None.
When it happens
Trigger: Calling Scope.Session.next_higher(), or any loop/helper that walks _ALL_SCOPES upward from Session without a bound. Produced by code paths in fixtures or plugins that ask for the next-higher scope, never by ini/CLI input.
Common situations: Plugin code that computes the enclosing scope of a session-scoped fixture; a refactor that walks scopes upward without checking for the top; tests that exercise Scope directly.
Related errors
- {self} is the lower-most scope
- function not available in {self.scope}-scoped context
- cls not available in {self.scope}-scoped context
- module not available in {self.scope}-scoped context
- path not available in {self.scope}-scoped context
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/46c3886d40c2f0bb.
Report an issue: GitHub.