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
- 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'})`.
- If renaming per-function, post-process the resulting frame's columns or index.
- 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
- Never use dict-of-dict to rename outputs; rename columns/index afterward.
- Audit old code for the {'col': {'new': 'func'}} pattern when upgrading pandas.
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
- cannot perform both aggregation and transformation operation
- Label(s) {list(cols)} do not exist
- axis other than 0 is not supported
- invalid value for result_type, must be one of {None, 'reduce
- Function names must be unique if there is no new column name
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/0e05416b11dad914.
Report an issue: GitHub.