{"record":{"id":"71c7074f89e28725","repo":"pandas-dev/pandas","slug":"func-is-expected-but-received-in-kwargs","errorCode":null,"errorMessage":"func is expected but received {} in **kwargs.","messagePattern":"func is expected but received (.+?) in \\*\\*kwargs\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/apply.py","lineNumber":2313,"sourceCode":"\n    Returns\n    -------\n    columns : List[str]\n        List of user-provided keys.\n    func : List[Union[str, callable[...,Any]]]\n        List of user-provided aggfuncs\n\n    Examples\n    --------\n    >>> validate_func_kwargs({\"one\": \"min\", \"two\": \"max\"})\n    (['one', 'two'], ['min', 'max'])\n    \"\"\"\n    tuple_given_message = \"func is expected but received {} in **kwargs.\"\n    columns = list(kwargs)\n    func = []\n    for col_func in kwargs.values():\n        if not (isinstance(col_func, str) or callable(col_func)):\n            raise TypeError(tuple_given_message.format(type(col_func).__name__))\n        func.append(col_func)\n    if not columns:\n        no_arg_message = \"Must provide 'func' or named aggregation **kwargs.\"\n        raise TypeError(no_arg_message)\n    return columns, func\n\n\ndef include_axis(op_name: Literal[\"agg\", \"apply\"], colg: Series | DataFrame) -> bool:\n    return isinstance(colg, ABCDataFrame) or (\n        isinstance(colg, ABCSeries) and op_name == \"agg\"\n    )\n","sourceCodeStart":2295,"sourceCodeEnd":2325,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/apply.py#L2295-L2325","documentation":"Raised by validate_func_kwargs (apply.py:2313) as a TypeError when, during named-aggregation parsing, one of the kwargs values is neither a string nor a callable. Named-aggregation kwargs must be either a (column, aggfunc) tuple or a NamedAgg; if pandas ends up validating a value that is some other type (e.g. an int or a bare tuple it tries to read as func), it reports which type it received via the {} placeholder.","triggerScenarios":"df.agg(out=(5,)) or any named-agg kwarg whose value (after tuple-unpacking) is not str/callable. Triggered in validate_func_kwargs at apply.py:2311-2313 when col_func fails isinstance(col_func, str) and not callable(col_func).","commonSituations":"Passing df.agg(name=42) by mistake; passing a dict-of-params instead of (column, func); mixing API styles so a value lands where pandas expects an aggfunc; misformatted tuples like (col,) missing the func element.","solutions":["Make each kwarg value either a string (e.g. 'sum') or a callable (e.g. np.mean), wrapped in the (column, func) tuple form: df.agg(out=('col','sum')).","Use pandas.NamedAgg for clarity: df.agg(out=pd.NamedAgg(column='col', aggfunc='sum')).","Validate kwargs types before calling agg: assert all(callable(v) or isinstance(v, str) for v in your_funcs.values())."],"exampleFix":"// before\ndf.agg(out=('col', 5))  # 5 is not a valid aggfunc\n// after\ndf.agg(out=('col', 'sum'))","handlingStrategy":"type-guard","validationCode":"for name, v in kwargs.items():\n    if not (isinstance(v, str) or callable(v)):\n        raise TypeError(f'kwarg {name!r} value {v!r} is not a str or callable')","typeGuard":"def named_agg_kwargs_valid(kwargs: dict) -> bool:\n    return all(isinstance(v, str) or callable(v) for v in kwargs.values())","tryCatchPattern":"try:\n    df.agg(**kwargs)\nexcept TypeError as e:\n    if 'func is expected' in str(e):\n        # coerce or drop offending kwargs\n        cleaned = {k: v for k, v in kwargs.items() if isinstance(v, str) or callable(v)}\n        df.agg(**cleaned)\n    else:\n        raise","preventionTips":["Always wrap named-agg values as (column, func) tuples or NamedAgg objects.","Validate dynamic kwargs before passing them to agg."],"tags":["pandas","agg","named-aggregation","type-error"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}