pandas-dev/pandas · error · TypeError

Must provide 'func' or tuples of '(column, aggfunc).

Error message

Must provide 'func' or tuples of '(column, aggfunc).

What it means

TypeError raised in reconstruct_func when neither a positional func nor any NamedAgg / relabeling kwargs were provided. The agg/apply call has nothing to compute, so pandas surfaces a clearer message than the downstream NoneType error.

Solutions

  1. Provide at least one positional function: df.agg('sum').
  2. Provide one or more named-aggregation kwargs: df.agg(a='sum').
  3. Guard the call site so that func=None is not passed (skip the call or default to a sensible function).

Example fix

# before
df.agg(None)
# after
df.agg('sum')
Defensive patterns

Strategy: validation

Validate before calling

def safe_agg(obj, func=None, **kwargs):
    if func is None and not kwargs:
        raise ValueError("agg requires a func or named-aggregation kwargs")
    return obj.agg(func, **kwargs) if func is not None else obj.agg(**kwargs)

Try / catch

try:
    df.agg(func)
except TypeError as e:
    if "Must provide" in str(e):
        df.agg('sum')  # sensible default
    else:
        raise

Prevention

When it happens

Trigger: df.agg(); df.agg(None); df.groupby('k').agg(None); calling agg with a func variable that resolved to None.

Common situations: Programmatic code where the func argument is computed from user input and defaults to None when nothing is selected.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/84844015fcad1abe. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/apply.py:1946

    relabeling = func is None and (
        is_multi_agg_with_relabel(**kwargs)
        or any(isinstance(v, NamedAgg) for v in kwargs.values())
    )

    columns: tuple[str, ...] | None = None
    order: npt.NDArray[np.intp] | None = None

    if not relabeling:
        if isinstance(func, list) and len(func) > len(set(func)):
            # GH 28426 will raise error if duplicated function names are used and
            # there is no reassigned name
            raise SpecificationError(
                "Function names must be unique if there is no new column names assigned"
            )
        if func is None:
            # nicer error message
            raise TypeError("Must provide 'func' or tuples of '(column, aggfunc).")

    if relabeling:
        normalization_needed = False
        # error: Incompatible types in assignment (expression has type
        # "MutableMapping[Hashable, list[Callable[..., Any] | str]]", variable has type
        # "Callable[..., Any] | str | list[Callable[..., Any] | str] |
        # MutableMapping[Hashable, Callable[..., Any] | str | list[Callable[..., Any] |
        # str]] | None")
        converted_kwargs = {}
        for key, val in kwargs.items():
            if isinstance(val, NamedAgg):
                column = val.column
                aggfunc = val.aggfunc
                if val.args or val.kwargs:
                    aggfunc = lambda x, func=aggfunc, a=val.args, kw=val.kwargs: func(
                        x, *a, **kw
                    )
            else:

View on GitHub (pinned to 3b7651241d)