pandas-dev/pandas · error · KeyError

Label(s) do not exist

Error message

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

What it means

Raised by `normalize_dictlike_arg` when, on a DataFrame, the keys of the dict-like func reference column labels that do not exist in `obj.columns`. Pandas computes the set difference and reports the missing labels so the user fixes the spec rather than getting a silently truncated result. Tracked via GH 58474.

Solutions

  1. Print `df.columns.tolist()` and compare against the dict keys to find the typo/mismatch.
  2. Strip/normalize column names right after reading data: `df.columns = df.columns.str.strip()`.
  3. Intersect keys with columns before calling: `spec = {k: v for k, v in spec.items() if k in df.columns}` (and warn on dropped keys).

Example fix

// before
df.agg({'Total': 'sum'})  # but column is 'total'
// after
df.agg({'total': 'sum'})
Defensive patterns

Strategy: validation

Validate before calling

def validate_agg_columns(df, spec):
    missing = [k for k in spec.keys() if k not in df.columns]
    if missing:
        raise KeyError(f'agg spec references missing columns: {missing}. ' f'Available: {list(df.columns)}')
    return spec

Type guard

def spec_keys_in_columns(spec, df) -> bool:
    cols = set(df.columns)
    return all(k in cols for k in spec.keys())

Try / catch

try:
    out = df.agg(spec)
except KeyError as e:
    if 'do not exist' in str(e):
        valid = {k: v for k, v in spec.items() if k in df.columns}
        out = df.agg(valid)
    else:
        raise

Prevention

When it happens

Trigger: `df.agg({'nonexistent_col': 'mean'})`, `df.transform({'typo_col': 'shift'})`, or any dict-spec whose keys include labels not in `df.columns`. Fires only when `obj.ndim != 1` (DataFrame path).

Common situations: Typos in column names, case mismatches ('Name' vs 'name'), trailing whitespace in column headers from CSV ingestion, or referencing columns after they were dropped/renamed earlier in the pipeline.

Related errors


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

Appendix: 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 3b7651241d)