pandas-dev/pandas · error · TypeError

func is expected but received {} in **kwargs.

Error message

func is expected but received {} in **kwargs.

What it means

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.

Source

Thrown at pandas/core/apply.py:2313

    Returns
    -------
    columns : List[str]
        List of user-provided keys.
    func : List[Union[str, callable[...,Any]]]
        List of user-provided aggfuncs

    Examples
    --------
    >>> validate_func_kwargs({"one": "min", "two": "max"})
    (['one', 'two'], ['min', 'max'])
    """
    tuple_given_message = "func is expected but received {} in **kwargs."
    columns = list(kwargs)
    func = []
    for col_func in kwargs.values():
        if not (isinstance(col_func, str) or callable(col_func)):
            raise TypeError(tuple_given_message.format(type(col_func).__name__))
        func.append(col_func)
    if not columns:
        no_arg_message = "Must provide 'func' or named aggregation **kwargs."
        raise TypeError(no_arg_message)
    return columns, func


def include_axis(op_name: Literal["agg", "apply"], colg: Series | DataFrame) -> bool:
    return isinstance(colg, ABCDataFrame) or (
        isinstance(colg, ABCSeries) and op_name == "agg"
    )

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. 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')).
  2. Use pandas.NamedAgg for clarity: df.agg(out=pd.NamedAgg(column='col', aggfunc='sum')).
  3. Validate kwargs types before calling agg: assert all(callable(v) or isinstance(v, str) for v in your_funcs.values()).

Example fix

// before
df.agg(out=('col', 5))  # 5 is not a valid aggfunc
// after
df.agg(out=('col', 'sum'))
Defensive patterns

Strategy: type-guard

Validate before calling

for name, v in kwargs.items():
    if not (isinstance(v, str) or callable(v)):
        raise TypeError(f'kwarg {name!r} value {v!r} is not a str or callable')

Type guard

def named_agg_kwargs_valid(kwargs: dict) -> bool:
    return all(isinstance(v, str) or callable(v) for v in kwargs.values())

Try / catch

try:
    df.agg(**kwargs)
except TypeError as e:
    if 'func is expected' in str(e):
        # coerce or drop offending kwargs
        cleaned = {k: v for k, v in kwargs.items() if isinstance(v, str) or callable(v)}
        df.agg(**cleaned)
    else:
        raise

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/71c7074f89e28725. Report an issue: GitHub.