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
- Flatten the spec: rename columns first (`df.rename(columns=...)` or `df = df.rename(...)`), then call `.agg({col: [funcs]})`.
- For Series.agg, use a list of funcs without a dict: `series.agg(['mean', 'sum'])`.
- 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
- Never use the legacy {'new_name': {'old_col': func}} syntax.
- Rename columns explicitly before agg.
- Add a spec-validation step in pipelines that ingest user-supplied agg dicts.
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
- axis other than 0 is not supported
- cannot combine transform and aggregation operations
- cannot perform both aggregation and transformation…
- Function names must be unique if there is no new column…
- Label(s) do not exist
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)