{"record":{"id":"84844015fcad1abe","repo":"pandas-dev/pandas","slug":"must-provide-func-or-tuples-of-column-aggfunc","errorCode":null,"errorMessage":"Must provide 'func' or tuples of '(column, aggfunc).","messagePattern":"Must provide 'func' or tuples of '\\(column, aggfunc\\)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/apply.py","lineNumber":1946,"sourceCode":"\n    relabeling = func is None and (\n        is_multi_agg_with_relabel(**kwargs)\n        or any(isinstance(v, NamedAgg) for v in kwargs.values())\n    )\n\n    columns: tuple[str, ...] | None = None\n    order: npt.NDArray[np.intp] | None = None\n\n    if not relabeling:\n        if isinstance(func, list) and len(func) > len(set(func)):\n            # GH 28426 will raise error if duplicated function names are used and\n            # there is no reassigned name\n            raise SpecificationError(\n                \"Function names must be unique if there is no new column names assigned\"\n            )\n        if func is None:\n            # nicer error message\n            raise TypeError(\"Must provide 'func' or tuples of '(column, aggfunc).\")\n\n    if relabeling:\n        normalization_needed = False\n        # error: Incompatible types in assignment (expression has type\n        # \"MutableMapping[Hashable, list[Callable[..., Any] | str]]\", variable has type\n        # \"Callable[..., Any] | str | list[Callable[..., Any] | str] |\n        # MutableMapping[Hashable, Callable[..., Any] | str | list[Callable[..., Any] |\n        # str]] | None\")\n        converted_kwargs = {}\n        for key, val in kwargs.items():\n            if isinstance(val, NamedAgg):\n                column = val.column\n                aggfunc = val.aggfunc\n                if val.args or val.kwargs:\n                    aggfunc = lambda x, func=aggfunc, a=val.args, kw=val.kwargs: func(\n                        x, *a, **kw\n                    )\n            else:","sourceCodeStart":1928,"sourceCodeEnd":1964,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/apply.py#L1928-L1964","documentation":"Raised by reconstruct_func (apply.py:1946) as a TypeError when func is None and the kwargs do not form a valid relabeling/named-aggregation spec. reconstruct_func accepts either a real func (string/callable/list/dict) or kwargs that look like named aggregation (column, aggfunc) tuples / NamedAgg objects; if neither is present the user has effectively passed nothing actionable.","triggerScenarios":"df.agg(None), df.agg(), or df.groupby('g').agg() with no positional func and no kwargs matching the named-aggregation shape. Triggered at apply.py:1944-1946 when func is None and the relabeling check at apply.py:1929-1932 returned False.","commonSituations":"Building the agg spec dynamically and ending up with an empty/None value; typo in the kwarg (e.g. df.agg(col=sum) without the tuple form); refactoring that stripped the positional arg; calling agg with a variable that evaluated to None.","solutions":["Pass a real func or named-aggregation kwargs: df.agg('sum'), df.agg({'a':'sum'}), or df.agg(out=('a','sum')).","If the spec is built dynamically, guard against empty/None before calling agg and skip the call or supply a default.","For named aggregation use the tuple form df.agg(new_name=(column, func)) or NamedAgg(column=..., aggfunc=...)."],"exampleFix":"// before\nspec = None  # accidentally empty\ndf.agg(spec)\n// after\ndf.agg('sum')\n// or named\nimport pandas as pd\ndf.agg(total=pd.NamedAgg(column='a', aggfunc='sum'))","handlingStrategy":"validation","validationCode":"if func is None and not kwargs:\n    raise TypeError(\"agg requires a func or named-aggregation kwargs\")","typeGuard":"def agg_has_spec(func, kwargs: dict) -> bool:\n    return func is not None or bool(kwargs)","tryCatchPattern":"try:\n    df.agg(func, **kwargs)\nexcept TypeError as e:\n    if \"Must provide 'func'\" in str(e):\n        df.agg('sum')  # sensible default\n    else:\n        raise","preventionTips":["Never call agg() with no arguments.","When building specs dynamically, fall back to a default like 'sum' if the spec resolves to None/empty."],"tags":["pandas","agg","missing-argument","named-aggregation"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}