pytest-dev/pytest · error · TypeError
{} expected string as 'msg' parameter, got '{}' instead. Per
Error message
{} expected string as 'msg' parameter, got '{}' instead.
Perhaps you meant to use a mark? What it means
OutcomeException.__init__ (base of Skipped/Failed/XFailed) requires msg to be a str or None. Passing any other type raises TypeError with a hint 'Perhaps you meant to use a mark?' because the common cause is calling pytest.skip/xfail/fail with a mark object or non-string reason.
Source
Thrown at src/_pytest/outcomes.py:23
import importlib
import sys
from typing import Any
from typing import ClassVar
from typing import NoReturn
class OutcomeException(BaseException):
"""OutcomeException and its subclass instances indicate and contain info
about test and collection outcomes."""
def __init__(self, msg: str | None = None, pytrace: bool = True) -> None:
if msg is not None and not isinstance(msg, str):
error_msg = ( # type: ignore[unreachable]
"{} expected string as 'msg' parameter, got '{}' instead.\n"
"Perhaps you meant to use a mark?"
)
raise TypeError(error_msg.format(type(self).__name__, type(msg).__name__))
super().__init__(msg)
self.msg = msg
self.pytrace = pytrace
def __repr__(self) -> str:
if self.msg is not None:
return self.msg
return f"<{self.__class__.__name__} instance>"
__str__ = __repr__
TEST_OUTCOME = (OutcomeException, Exception)
class Skipped(OutcomeException):
# XXX hackish: on 3k we fake to live in the builtins
# in order to have Skipped exception printing shorter/nicerView on GitHub (pinned to 98b357f69e)
Solutions
- Pass a string reason: pytest.skip('reason text')
- If you meant a marker, use the decorator: @pytest.mark.skip(reason='...')
- Convert the object to a string first: pytest.skip(str(obj))
Example fix
// before pytest.skip(some_exception) // after pytest.skip(str(some_exception))
Defensive patterns
Strategy: type-guard
Validate before calling
def safe_skip(reason):
if reason is not None and not isinstance(reason, str):
reason = str(reason)
import pytest; pytest.skip(reason) Type guard
def is_str_or_none(msg) -> bool:
return msg is None or isinstance(msg, str) Prevention
- Always pass a string reason to pytest.skip/fail/xfail
- For decorator behavior use @pytest.mark.skip / @pytest.mark.xfail, not the function form
When it happens
Trigger: pytest.skip(some_object), pytest.fail(exception_instance), or pytest.xfail(reason) where reason is not a string. Also triggered by raising Skipped/Failed directly with a non-str arg.
Common situations: Calling pytest.skip(SomeException) intending to re-raise; passing a marker decorator where a reason string is expected; mixing up pytest.mark.skip with pytest.skip.
Related errors
- module {modname!r} has __version__ {verattr!r}, required is:
- {cat} is not a Warning subclass
- invalid type for ini option {name!r}: {type_!r} (expected on
- invalid type for ini option {name!r}: Literal choices must b
- warning must be an instance of Warning or subclass, got {war
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/9e8a88e10b26884f.json.
Report an issue: GitHub.