pytest-dev/pytest · error · TypeError
{str(e)} - maybe you meant pytest.mark.skipif?
Error message
{str(e)} - maybe you meant pytest.mark.skipif? What it means
Raised when @pytest.mark.skip is applied with arguments that the Skip dataclass cannot accept, almost always because the author meant @pytest.mark.skipif. skip's dataclass (reason, allow_module_level) does not take a positional condition, so Skip(*mark.args, **mark.kwargs) raises TypeError, which pytest re-raises with a helpful suffix suggesting skipif.
Source
Thrown at src/_pytest/skipping.py:192
else:
conditions = (mark.kwargs["condition"],)
# Unconditional.
if not conditions:
reason = mark.kwargs.get("reason", "")
return Skip(reason)
# If any of the conditions are true.
for condition in conditions:
result, reason = evaluate_condition(item, mark, condition)
if result:
return Skip(reason)
for mark in item.iter_markers(name="skip"):
try:
return Skip(*mark.args, **mark.kwargs)
except TypeError as e:
raise TypeError(str(e) + " - maybe you meant pytest.mark.skipif?") from None
return None
@dataclasses.dataclass(frozen=True)
class Xfail:
"""The result of evaluate_xfail_marks()."""
__slots__ = ("raises", "reason", "run", "strict")
reason: str
run: bool
strict: bool
raises: (
type[BaseException]
| tuple[type[BaseException], ...]
| AbstractRaises[BaseException]
| NoneView on GitHub (pinned to 98b357f69e)
Solutions
- Use @pytest.mark.skipif(condition, reason=...) for conditional skipping.
- For unconditional skip, use @pytest.mark.skip with no args, or @pytest.mark.skip(reason='...').
- If you need module-level skipping, use pytestmark = pytest.mark.skip or skip(allow_module_level=True).
Example fix
// before @pytest.mark.skip(sys.platform == "win32") def test_windows_only(): ... // after @pytest.mark.skipif(sys.platform == "win32", reason="windows only") def test_windows_only(): ...
Defensive patterns
Strategy: validation
Validate before calling
import inspect, pytest
def assert_skip_marks_valid(module):
for _, obj in inspect.getmembers(module, inspect.isfunction):
for mark in getattr(obj, "pytestmark", []):
if mark.name == "skip" and mark.args:
raise TypeError(f"{obj.__name__}: skip with positional args; use skipif") Type guard
import pytest
def is_unconditional_skip(mark: pytest.Mark) -> bool:
return mark.name == "skip" and not mark.args Prevention
- Reserve @pytest.mark.skip for unconditional skips (optionally with reason=).
- Use @pytest.mark.skipif for any condition-based skip.
- Lint in CI: grep for 'mark.skip(' followed by something other than 'reason='.
When it happens
Trigger: Writing @pytest.mark.skip(sys.platform == 'win32') or @pytest.mark.skip(condition) at the top of a test. The TypeError fires during mark evaluation at collection/run time when evaluate_skip_marks tries to construct Skip from the bad mark.
Common situations: Copy-pasting from skipif examples without changing the marker name; coming from unittest.skip (which does accept a condition / reason string) and assuming pytest's skip mirrors it; conditional skip intent but unconditional-skip syntax.
Related errors
- pytest_markeval_namespace() needs to return a dict, got {dic
- got {mark_obj!r} instead of Mark
- Marker name must NOT start with underscore
- {} expected string as 'msg' parameter, got '{}' instead. Per
- module {modname!r} has __version__ {verattr!r}, required is:
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/a6fbf206758619ee.json.
Report an issue: GitHub.