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]
        | None

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Use @pytest.mark.skipif(condition, reason=...) for conditional skipping.
  2. For unconditional skip, use @pytest.mark.skip with no args, or @pytest.mark.skip(reason='...').
  3. 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

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


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