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

In the function-call form of pytest.warns, the second positional argument (func) must be callable. It will be invoked inside the warning-checking context.

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 98b357f69e)

Solutions

  1. Pass the callable itself, not its return value.
  2. Verify with callable(obj) when the value is dynamic.
  3. Switch to the context-manager form (with pytest.warns(UserWarning):) to avoid the positional-func pitfall.

Example fix

// before
pytest.warns(UserWarning, my_func())
// after
pytest.warns(UserWarning, my_func)
Defensive patterns

Strategy: type-guard

Validate before calling

if not callable(func):
    raise TypeError(f'{func!r} is not callable')
pytest.warns(UserWarning, func)

Type guard

from collections.abc import Callable
def is_callable_warn_func(f) -> TypeGuard[Callable]:
    return callable(f)

Prevention

When it happens

Trigger: Calling pytest.warns(UserWarning, 42) or pytest.warns(UserWarning, 'notafunc'). Hits recwarn.py:170 (`if not callable(func):`).

Common situations: Passing the result of a call instead of the callable reference; passing a module or data object; a refactor removed the callable.

Related errors


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