pytest-dev/pytest · error · TypeError
got {mark_obj!r} instead of Mark
Error message
got {mark_obj!r} instead of Mark What it means
`normalize_mark_list` iterates items passed as marks and unwraps `MarkDecorator` via its `.mark` attribute; anything that is not ultimately a `Mark` instance raises TypeError. This guards internal mark normalization used by parametrize and `pytestmark`.
Source
Thrown at src/_pytest/mark/structures.py:480
else:
mark_list = [mark_attribute]
return list(normalize_mark_list(mark_list))
def normalize_mark_list(
mark_list: Iterable[Mark | MarkDecorator],
) -> Iterable[Mark]:
"""
Normalize an iterable of Mark or MarkDecorator objects into a list of marks
by retrieving the `mark` attribute on MarkDecorator instances.
:param mark_list: marks to normalize
:returns: A new list of the extracted Mark objects
"""
for mark in mark_list:
mark_obj = getattr(mark, "mark", mark)
if not isinstance(mark_obj, Mark):
raise TypeError(f"got {mark_obj!r} instead of Mark")
yield mark_obj
def store_mark(obj, mark: Mark) -> None:
"""Store a Mark on an object.
This is used to implement the Mark declarations/decorators correctly.
"""
assert isinstance(mark, Mark), mark
from ..fixtures import getfixturemarker
if getfixturemarker(obj) is not None:
fail(
"Marks cannot be applied to fixtures.\n"
"See docs: https://docs.pytest.org/en/stable/deprecations.html#applying-a-mark-to-a-fixture-function"
)
View on GitHub (pinned to 98b357f69e)
Solutions
- Ensure each item in `marks=[...]` is a `Mark` or `MarkDecorator` (e.g. `pytest.mark.skip`, `pytest.mark.xfail(reason=...)`).
- Drop custom decorators that are not pytest marks from the marks list.
- If you constructed marks manually, use `pytest.Mark(name, args, kwargs)`.
Example fix
# before
@pytest.mark.parametrize('x', [pytest.param(1, marks=[my_custom_decorator)])
# after
@pytest.mark.parametrize('x', [pytest.param(1, marks=[pytest.mark.skip])]) Defensive patterns
Strategy: type-guard
Validate before calling
from _pytest.mark.structures import Mark, MarkDecorator
def all_real_marks(marks) -> bool:
return all(isinstance(m, (Mark, MarkDecorator)) for m in marks) Type guard
from _pytest.mark.structures import Mark, MarkDecorator
def is_mark_like(m: object) -> bool:
return isinstance(m, (Mark, MarkDecorator)) Prevention
- Only put `pytest.mark.*` results in `marks=[...]`.
- Keep custom decorators out of mark lists.
When it happens
Trigger: Passing a plain string, int, function, or a decorator that is not a `MarkDecorator` inside `marks=[...]` of `pytest.param`, or assigning non-mark objects to `pytestmark`.
Common situations: Mixing custom decorators with pytest marks; passing `pytest.mark.foo` incorrectly (e.g. `pytest.mark` itself, or an already-called decorator returning a non-mark); stale third-party helpers that return raw callables.
Related errors
- Expected id to be a string or a `pytest.HIDDEN_PARAM` sentin
- Marker name must NOT start with underscore
- must be absolute import path string, not {import_path!r}
- use setattr(target, name, value) or setattr(target, value) w
- use setattr(target, name, value) with name being a string or
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/71a1ec4b8c9962fe.json.
Report an issue: GitHub.