pytest-dev/pytest · error · TypeError
object (type: ) must be callable
Error message
{func!r} object (type: {type(func)}) must be callable What it means
Raised by pytest.warns in its function form when the second positional argument (func) is not callable. The function form pytest.warns(Warning, func, *args, **kwargs) wraps and calls func inside a WarningsChecker; a non-callable func cannot be invoked, so pytest rejects it with the offending repr and type.
Solutions
- Pass an actual callable: pytest.warns(UserWarning, my_function, arg1, arg2).
- If you meant the context-manager form, omit func entirely: with pytest.warns(UserWarning): my_function(arg1).
- Verify callable(func) is True before invoking the function form.
Example fix
// before
pytest.warns(UserWarning, 'emit_warning')
// after
pytest.warns(UserWarning, emit_warning)
// or context-manager form:
with pytest.warns(UserWarning):
emit_warning() Defensive patterns
Strategy: type-guard
Validate before calling
assert func is None or callable(func), f'pytest.warns function form requires a callable, got {func!r}' Type guard
def warns_func_callable(func) -> bool:
return func is None or callable(func) Prevention
- Verify the second positional arg to pytest.warns is a function reference, not a string or module.
- Prefer the context-manager form when in doubt to avoid the callable check.
- In helpers, assert callable(func) before forwarding.
When it happens
Trigger: pytest.warns(UserWarning, 'some_function'); pytest.warns(UserWarning, None, 1, 2); pytest.warns(UserWarning, some_module) where some_module is a module object, not a function.
Common situations: Forgetting to call a decorator/wrapper that returns a non-callable; passing a module instead of its function; passing a string name instead of the function reference.
Related errors
- Unexpected keyword arguments passed to pytest.warns
- `allow_unwrapped=True` bypasses the `match` and `check`…
- `allow_unwrapped=True` has no effect when expecting a…
- Cannot enter twice
- Cannot exit without entering first
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/174b1d16d5a601fc.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/recwarn.py:170
such that some runs raise a warning and others do not.
This could be achieved in the same way as with exceptions, see
:ref:`parametrizing_conditional_raising` for an example.
"""
__tracebackhide__ = True
if func is None and not args:
match: str | re.Pattern[str] | None = kwargs.pop("match", None)
if kwargs:
argnames = ", ".join(sorted(kwargs))
raise TypeError(
f"Unexpected keyword arguments passed to pytest.warns: {argnames}"
"\nUse context-manager form instead?"
)
return WarningsChecker(expected_warning, match_expr=match, _ispytest=True)
else:
if not callable(func):
raise TypeError(f"{func!r} object (type: {type(func)}) must be callable")
with WarningsChecker(expected_warning, _ispytest=True):
return func(*args, **kwargs)
class WarningsRecorder(warnings.catch_warnings):
"""A context manager to record raised warnings.
Each recorded warning is an instance of :class:`warnings.WarningMessage`.
Adapted from `warnings.catch_warnings`.
.. note::
``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
differently; see :ref:`ensuring_function_triggers`.
"""
def __init__(self, *, _ispytest: bool = False) -> None:View on GitHub (pinned to 0d6fbdeffa)