pandas-dev/pandas · error · SpecificationError

nested renamer is not supported

Error message

nested renamer is not supported

What it means

Raised in `normalize_dictlike_arg` when a dict-like function spec contains nested dict values (a 'renamer'), e.g. `{'A': {'new_name': 'mean'}}`. This deprecated/removed pattern (GH 15931) let users rename outputs inline; the supported replacement is to specify output names via the outer dict keys and a flat list of functions as values.

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 71959b8cb9)

Solutions

  1. Flatten the spec: use the outer key as the column, the value as a list of functions, then rename columns of the result afterward: `df.agg({'A': ['mean', 'sum']}).rename(columns={'A': 'renamed_A'})`.
  2. If renaming per-function, post-process the resulting frame's columns or index.
  3. Audit for any dict-valued entries in your agg spec and convert them to lists.

Example fix

# before
df.agg({'A': {'renamed_A': 'mean'}})
# after
out = df.agg({'A': ['mean']})
out.columns = ['renamed_A']
Defensive patterns

Strategy: validation

Validate before calling

def flatten_spec(spec):
    """Reject or flatten nested-dict (renamer) specs."""
    out = {}
    for k, v in spec.items():
        if isinstance(v, dict):
            raise ValueError(f'nested renamer at {k!r}; flatten to list of funcs')
        out[k] = v
    return out

# usage
df.agg(flatten_spec(my_spec))

Type guard

def is_flat_spec(spec) -> bool:
    return all(not isinstance(v, dict) for v in spec.values())

Try / catch

from pandas.errors import SpecificationError
try:
    df.agg(spec)
except SpecificationError as e:
    if 'nested renamer' in str(e):
        # flatten the spec manually then retry
        ...
    raise

Prevention

When it happens

Trigger: `df.agg({'A': {'renamed_A': 'mean'}})` — the value is itself a dict, which is treated as a nested renamer. Also `series.agg({'x': {'y': 'sum'}})` or any dict-of-dict input.

Common situations: Old tutorials/code predating GH 15931 using the renamer pattern; copy-paste from Stack Overflow answers; migrating from a version that warned to one that raises.

Related errors


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