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

  1. Pass the callable itself, not its result: drop the trailing parentheses on the function name.
  2. Verify with callable(obj) before passing when the value comes from a dynamic source.
  3. Switch to the context-manager form (with pytest.raises(ValueError):) to avoid the positional-func footgun entirely.
  4. 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

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


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