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

  1. Rename the marker so it does not start with an underscore.
  2. 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

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


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