pandas-dev/pandas · error · KeyError

Label(s) {list(cols)} do not exist

Error message

Label(s) {list(cols)} do not exist

What it means

Raised in `normalize_dictlike_arg` when a dict-like function spec references column labels that do not exist in the DataFrame's columns. The check computes the set difference between the dict keys and `obj.columns`; any missing labels are reported. Added/strengthened in GH#58474 to fail fast rather than silently producing NaN results.

Source

Thrown at pandas/core/apply.py:803

        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 = {}
            for k, v in func.items():
                if not isinstance(v, aggregator_types):
                    new_func[k] = [v]
                else:
                    new_func[k] = v
            func = new_func
        return func

    def _apply_str(self, obj, func: str, *args, **kwargs):

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Verify the dict keys against `df.columns` before calling: `missing = set(func_dict) - set(df.columns)`.
  2. Use `Intersection`/filtering: `{k: v for k, v in func_dict.items() if k in df.columns}`.
  3. Fix the typo or restore the missing column upstream in the pipeline.

Example fix

# before
df.agg({'total': 'sum'})  # column is actually 'totals'
# after
df.agg({'totals': 'sum'})
# or guard dynamically
ops = {k: v for k, v in ops.items() if k in df.columns}
Defensive patterns

Strategy: validation

Validate before calling

def safe_agg(df, spec):
    missing = set(spec) - set(df.columns)
    if missing:
        raise KeyError(f'columns not in df: {missing}')
    return df.agg(spec)

Type guard

def spec_keys_in_columns(spec, df) -> bool:
    return set(spec).issubset(set(df.columns))

Try / catch

try:
    df.agg(spec)
except KeyError as e:
    # filter spec to existing columns and retry, or surface a clear error
    valid = {k: v for k, v in spec.items() if k in df.columns}
    df.agg(valid)

Prevention

When it happens

Trigger: `df.agg({'nonexistent_col': 'mean'})` on a DataFrame lacking that column. Also dynamic dict construction where a key is misspelled or refers to a column dropped earlier in the pipeline.

Common situations: Typos in column names; refactoring where columns are renamed/dropped but agg specs are not updated; building the dict from an external schema that drifted from the data.

Related errors


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