pytest-dev/pytest · error · TypeError
exceptions must be derived from Warning, not %s
Error message
exceptions must be derived from Warning, not %s
What it means
In WarningsChecker, every element of a tuple passed as expected_warning must be a subclass of Warning. Passing a non-Warning type (e.g. an exception class) in the tuple is rejected.
Source
Thrown at src/_pytest/recwarn.py:280
@final
class WarningsChecker(WarningsRecorder):
def __init__(
self,
expected_warning: type[Warning] | tuple[type[Warning], ...] = Warning,
match_expr: str | re.Pattern[str] | None = None,
*,
_ispytest: bool = False,
) -> None:
check_ispytest(_ispytest)
super().__init__(_ispytest=True)
msg = "exceptions must be derived from Warning, not %s"
if isinstance(expected_warning, tuple):
for exc in expected_warning:
if not issubclass(exc, Warning):
raise TypeError(msg % type(exc))
expected_warning_tup = expected_warning
elif isinstance(expected_warning, type) and issubclass(
expected_warning, Warning
):
expected_warning_tup = (expected_warning,)
else:
raise TypeError(msg % type(expected_warning))
self.expected_warning = expected_warning_tup
self.match_expr = match_expr
def matches(self, warning: warnings.WarningMessage) -> bool:
assert self.expected_warning is not None
return issubclass(warning.category, self.expected_warning) and bool(
self.match_expr is None or re.search(self.match_expr, str(warning.message))
)
def __exit__(View on GitHub (pinned to 98b357f69e)
Solutions
- Use only Warning subclasses in the tuple: pytest.warns((UserWarning, RuntimeWarning)).
- Verify each element with issubclass(x, Warning) before passing when constructed dynamically.
- Remember warns is for warnings (Warning subclasses), raises is for exceptions (BaseException subclasses).
Example fix
// before pytest.warns((UserWarning, ValueError)) // after pytest.warns((UserWarning, RuntimeWarning))
Defensive patterns
Strategy: type-guard
Validate before calling
for exc in expected_warning:
if not (isinstance(exc, type) and issubclass(exc, Warning)):
raise TypeError(f'{exc!r} is not a Warning subclass')
pytest.warns(expected_warning) Type guard
def all_are_warning_types(excs) -> TypeGuard[tuple[type[Warning], ...]]:
return isinstance(excs, tuple) and all(isinstance(e, type) and issubclass(e, Warning) for e in excs) Prevention
- Use only Warning subclasses (UserWarning, DeprecationWarning, etc.) in warns tuples.
- Validate each tuple element with issubclass(x, Warning) for dynamic construction.
- Remember: warns takes Warning subclasses; raises takes BaseException subclasses.
When it happens
Trigger: Calling pytest.warns((UserWarning, ValueError)) — ValueError is an exception, not a Warning. Hits recwarn.py:280 inside the tuple loop.
Common situations: Mixing exception classes with warning classes; typo; assuming warns accepts exception types like raises does.
Related errors
- Warning must be str or Warning, got {msg!r} (type {type(msg)
- Expected {expected}, but got {exc.__name__!r}
- Expected {expected}, but got an exception instance: {type(ex
- Unexpected keyword arguments passed to pytest.warns: {argnam
- {func!r} object (type: {type(func)}) must be callable
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/577b311e374bdb7c.json.
Report an issue: GitHub.