pytest-dev/pytest · error · AttributeError
Marker name must NOT start with underscore
Error message
Marker name must NOT start with underscore
What it means
`MarkGenerator.__getattr__` is what makes `pytest.mark.<name>` work. It refuses names beginning with `_` to prevent collision with internal/dunder attributes (and accidental access to private generator state like `_config`). It raises AttributeError with this message.
Source
Thrown at src/_pytest/mark/structures.py:600
# See TYPE_CHECKING above.
if TYPE_CHECKING:
skip: _SkipMarkDecorator
skipif: _SkipifMarkDecorator
xfail: _XfailMarkDecorator
parametrize: _ParametrizeMarkDecorator
usefixtures: _UsefixturesMarkDecorator
filterwarnings: _FilterwarningsMarkDecorator
def __init__(self, *, _ispytest: bool = False) -> None:
check_ispytest(_ispytest)
self._config: Config | None = None
self._markers: set[str] = set()
def __getattr__(self, name: str) -> MarkDecorator:
"""Generate a new :class:`MarkDecorator` with the given name."""
if name[0] == "_":
raise AttributeError("Marker name must NOT start with underscore")
if self._config is not None:
# We store a set of markers as a performance optimisation - if a mark
# name is in the set we definitely know it, but a mark may be known and
# not in the set. We therefore start by updating the set!
if name not in self._markers:
for line in self._config.getini("markers"):
# example lines: "skipif(condition): skip the given test if..."
# or "hypothesis: tests which use Hypothesis", so to get the
# marker name we split on both `:` and `(`.
marker = line.split(":")[0].split("(")[0].strip()
self._markers.add(marker)
# If the name is not in the set of known marks after updating,
# then it really is time to issue a warning or an error.
if name not in self._markers:
# Raise a specific error for common misspellings of "parametrize".
if name in ["parameterize", "parametrise", "parameterise"]:View on GitHub (pinned to 98b357f69e)
Solutions
- Rename the marker so it does not start with an underscore.
- When generating marker names from external input, strip or reject leading underscores.
Example fix
# before @pytest.mark._internal def test_x(): ... # after @pytest.mark.internal def test_x(): ...
Defensive patterns
Strategy: validation
Validate before calling
def marker_name_ok(name: str) -> bool:
return not name.startswith('_') Type guard
def is_public_marker_name(name: object) -> bool:
return isinstance(name, str) and not name.startswith('_') Prevention
- Register custom markers without leading underscores.
- Sanitize generated marker names from external input.
When it happens
Trigger: `pytest.mark._foo`, `pytest.mark.__something`, or any access `getattr(pytest.mark, '_x')`.
Common situations: Programmatically constructing marker names from input that may start with `_`; copying internal-style names.
Related errors
- got {mark_obj!r} instead of Mark
- {type(obj).__name__!r} object at {ann} has no attribute {nam
- {target!r} has no attribute {name!r}
- absolute tolerance can't be NaN.
- relative tolerance can't be negative: {relative_tolerance}
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/3688cf92b72ddc22.json.
Report an issue: GitHub.