pandas-dev/pandas · error · SpecificationError

nested renamer is not supported

Error message

nested renamer is not supported

What it means

Raised by `normalize_dictlike_arg` as a `SpecificationError` when the dict-like func passed to agg/apply/transform contains nested dict values (a 'nested renamer'), or when a Series.agg is given list-like values. Since GH 15931 pandas no longer supports the old renaming syntax `{'new_name': {'old_col': 'mean'}}`; the dict shape must map columns directly to functions/lists-of-functions.

Solutions

  1. Flatten the spec: rename columns first (`df.rename(columns=...)` or `df = df.rename(...)`), then call `.agg({col: [funcs]})`.
  2. For Series.agg, use a list of funcs without a dict: `series.agg(['mean', 'sum'])`.
  3. If you want named outputs from a list, use named aggregations or rename the result Series afterwards.

Example fix

// before
df.agg({'result': {'A': 'mean'}})
// after
df[['A']].agg({'A': 'mean'}).rename('result')
Defensive patterns

Strategy: validation

Validate before calling

def flatten_agg_spec(df, spec):
    import collections.abc as cabc
    # Reject nested dicts (renamers); require flat column -> func/list-of-funcs.
    for k, v in spec.items():
        if isinstance(v, cabc.Mapping):
            raise ValueError(f'nested renamer at key {k!r}; flatten the spec')
    return spec

Type guard

def is_flat_agg_spec(spec) -> bool:
    import collections.abc as cabc
    return all(not isinstance(v, cabc.Mapping) for v in spec.values())

Try / catch

from pandas.errors import SpecificationError
try:
    out = df.agg(spec)
except SpecificationError as e:
    if 'nested renamer' in str(e):
        # flatten by pre-renaming columns
        out = df.rename(columns={k: list(v)[0] for k, v in spec.items()}).agg(...)
    else:
        raise

Prevention

When it happens

Trigger: `df.agg({'result': {'A': 'mean'}})` (nested dict), `series.agg({'x': ['mean', 'sum']})` (list values on a Series), or any dict whose values are themselves dict-like. Fires for how in ('apply','agg','transform') when the nested condition matches.

Common situations: Legacy pandas code using the pre-0.20 / pre-0.25 renaming-dict syntax; copy-pasted StackOverflow answers from old pandas versions; attempting to rename-and-aggregate in one shot.

Related errors


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

Appendix: source

Thrown at pandas/core/apply.py:794

        self, how: str, obj: DataFrame | Series, func: AggFuncTypeDict
    ) -> AggFuncTypeDict:
        """
        Handler for dict-like argument.

        Ensures that necessary columns exist if obj is a DataFrame, and
        that a nested renamer is not passed. Also normalizes to all lists
        when values consists of a mix of list and non-lists.
        """
        assert how in ("apply", "agg", "transform")

        # Can't use func.values(); wouldn't work for a Series
        if (
            how == "agg"
            and isinstance(obj, ABCSeries)
            and any(is_list_like(v) for _, v in func.items())
        ) or (any(is_dict_like(v) for _, v in func.items())):
            # GH 15931 - deprecation of renaming keys
            raise SpecificationError("nested renamer is not supported")

        if obj.ndim != 1:
            # Check for missing columns on a frame
            from pandas import Index

            cols = Index(list(func.keys())).difference(obj.columns, sort=True)
            if len(cols) > 0:
                # GH 58474
                raise KeyError(f"Label(s) {list(cols)} do not exist")

        aggregator_types = (list, tuple, dict)

        # if we have a dict of any non-scalars
        # eg. {'A' : ['mean']}, normalize all to
        # be list-likes
        # Cannot use func.values() because arg may be a Series
        if any(isinstance(x, aggregator_types) for _, x in func.items()):
            new_func: AggFuncTypeDict = {}

View on GitHub (pinned to 3b7651241d)