pytest-dev/pytest · error · TypeError
{func!r} object (type: {type(func)}) must be callable
Error message
{func!r} object (type: {type(func)}) must be callable What it means
Raised in the function-call form of pytest.raises when the second positional argument (func) is not callable. The function-call signature requires func to be a callable that will be invoked with the trailing *args/**kwargs.
Source
Thrown at src/_pytest/raises.py:275
if func is None and not args:
if set(kwargs) - {"match", "check", "expected_exception"}:
msg = "Unexpected keyword arguments passed to pytest.raises: "
msg += ", ".join(sorted(kwargs))
msg += "\nUse context-manager form instead?"
raise TypeError(msg)
if expected_exception is None:
return RaisesExc(**kwargs)
return RaisesExc(expected_exception, **kwargs)
if not expected_exception:
raise ValueError(
f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. "
f"Raising exceptions is already understood as failing the test, so you don't need "
f"any special code to say 'this should never raise an exception'."
)
if not callable(func):
raise TypeError(f"{func!r} object (type: {type(func)}) must be callable")
with RaisesExc(expected_exception) as excinfo:
func(*args, **kwargs)
try:
return excinfo
finally:
del excinfo
# note: RaisesExc/RaisesGroup uses fail() internally, so this alias
# indicates (to [internal] plugins?) that `pytest.raises` will
# raise `_pytest.outcomes.Failed`, where
# `outcomes.Failed is outcomes.fail.Exception is raises.Exception`
# note: this is *not* the same as `_pytest.main.Failed`
# note: mypy does not recognize this attribute, and it's not possible
# to use a protocol/decorator like the others in outcomes due to
# https://github.com/python/mypy/issues/18715
raises.Exception = fail.Exception # type: ignore[attr-defined]
View on GitHub (pinned to 98b357f69e)
Solutions
- Pass the callable itself, not its result: drop the trailing parentheses on the function name.
- Verify with callable(obj) before passing when the value comes from a dynamic source.
- Switch to the context-manager form (with pytest.raises(ValueError):) to avoid the positional-func footgun entirely.
- Check for a typo or stale reference if a refactor may have removed the callable.
Example fix
// before pytest.raises(ValueError, my_func()) // after pytest.raises(ValueError, my_func)
Defensive patterns
Strategy: type-guard
Validate before calling
if not callable(func):
raise TypeError(f'{func!r} is not callable')
pytest.raises(ValueError, func) Type guard
from collections.abc import Callable
def is_callable_func(f) -> TypeGuard[Callable]:
return callable(f) Prevention
- Pass the function reference (no parentheses), not its return value.
- Prefer the context-manager form (with pytest.raises(Exc):) to avoid the positional func entirely.
- When func comes from a dynamic source, assert callable(func) first.
When it happens
Trigger: Calling pytest.raises(ValueError, 42), pytest.raises(ValueError, 'notafunc'), or pytest.raises(ValueError, some_object) where the second arg is not callable. Hits raises.py:274 (`if not callable(func):`).
Common situations: Accidentally calling the function (passing its return value) instead of passing the reference; passing a module or data object by mistake; a refactor renames the function so the name no longer resolves to a callable.
Related errors
- Expected an exception type or a tuple of exception types, bu
- Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[Base
- Expected {expected}, but got {exc.__name__!r}
- Expected {expected}, but got an exception instance: {type(ex
- You must specify at least one parameter to match on.
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/85f37b89487a62e0.json.
Report an issue: GitHub.