{"id":"174b1d16d5a601fc","repo":"pytest-dev/pytest","slug":"func-r-object-type-type-func-must-be-calla-174b1d","errorCode":null,"errorMessage":"{func!r} object (type: {type(func)}) must be callable","messagePattern":"(.+?) object \\(type: (.+?)\\) must be callable","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/recwarn.py","lineNumber":170,"sourceCode":"    such that some runs raise a warning and others do not.\n\n    This could be achieved in the same way as with exceptions, see\n    :ref:`parametrizing_conditional_raising` for an example.\n\n    \"\"\"\n    __tracebackhide__ = True\n    if func is None and not args:\n        match: str | re.Pattern[str] | None = kwargs.pop(\"match\", None)\n        if kwargs:\n            argnames = \", \".join(sorted(kwargs))\n            raise TypeError(\n                f\"Unexpected keyword arguments passed to pytest.warns: {argnames}\"\n                \"\\nUse context-manager form instead?\"\n            )\n        return WarningsChecker(expected_warning, match_expr=match, _ispytest=True)\n    else:\n        if not callable(func):\n            raise TypeError(f\"{func!r} object (type: {type(func)}) must be callable\")\n        with WarningsChecker(expected_warning, _ispytest=True):\n            return func(*args, **kwargs)\n\n\nclass WarningsRecorder(warnings.catch_warnings):\n    \"\"\"A context manager to record raised warnings.\n\n    Each recorded warning is an instance of :class:`warnings.WarningMessage`.\n\n    Adapted from `warnings.catch_warnings`.\n\n    .. note::\n        ``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated\n        differently; see :ref:`ensuring_function_triggers`.\n\n    \"\"\"\n\n    def __init__(self, *, _ispytest: bool = False) -> None:","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/recwarn.py#L152-L188","documentation":"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.","triggerScenarios":"Calling pytest.warns(UserWarning, 42) or pytest.warns(UserWarning, 'notafunc'). Hits recwarn.py:170 (`if not callable(func):`).","commonSituations":"Passing the result of a call instead of the callable reference; passing a module or data object; a refactor removed the callable.","solutions":["Pass the callable itself, not its return value.","Verify with callable(obj) when the value is dynamic.","Switch to the context-manager form (with pytest.warns(UserWarning):) to avoid the positional-func pitfall."],"exampleFix":"// before\npytest.warns(UserWarning, my_func())\n// after\npytest.warns(UserWarning, my_func)","handlingStrategy":"type-guard","validationCode":"if not callable(func):\n    raise TypeError(f'{func!r} is not callable')\npytest.warns(UserWarning, func)","typeGuard":"from collections.abc import Callable\ndef is_callable_warn_func(f) -> TypeGuard[Callable]:\n    return callable(f)","tryCatchPattern":null,"preventionTips":["Pass the callable reference, not the result of calling it.","Prefer the context-manager form to avoid the positional func pitfall.","Assert callable(func) when func is dynamically sourced."],"tags":["pytest","warns","validation","callable"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}