{"record":{"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/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/recwarn.py#L152-L188","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npytest.warns(UserWarning, 'emit_warning')\n// after\npytest.warns(UserWarning, emit_warning)\n// or context-manager form:\nwith pytest.warns(UserWarning):\n    emit_warning()","handlingStrategy":"type-guard","validationCode":"assert func is None or callable(func), f'pytest.warns function form requires a callable, got {func!r}'","typeGuard":"def warns_func_callable(func) -> bool:\n    return func is None or callable(func)","tryCatchPattern":null,"preventionTips":["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."],"tags":["pytest","warns","callable","api-misuse","validation"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}