pandas-dev/pandas · error · KeyError

Column not found: {key}

Error message

Column not found: {key}

What it means

Raised by SelectionMixin.__getitem__ for a single (scalar) key that is not present in obj. The scalar branch complements the list branch (476); reports the missing key.

Source

Thrown at pandas/core/base.py:224

        if len(self.exclusions) > 0:
            return self.obj._drop_axis(self.exclusions, axis=1)
        else:
            return self.obj

    def __getitem__(self, key):
        if self._selection is not None:
            raise IndexError(f"Column(s) {self._selection} already selected")

        if isinstance(key, (list, tuple, ABCSeries, ABCIndex, np.ndarray)):
            if len(self.obj.columns.intersection(key)) != len(set(key)):
                bad_keys = list(set(key).difference(self.obj.columns))
                raise KeyError(f"Columns not found: {str(bad_keys)[1:-1]}")
            return self._gotitem(list(key), ndim=2)

        else:
            if key not in self.obj:
                raise KeyError(f"Column not found: {key}")
            ndim = self.obj[key].ndim
            return self._gotitem(key, ndim=ndim)

    def _gotitem(self, key, ndim: int, subset=None):
        """
        sub-classes to define
        return a sliced object

        Parameters
        ----------
        key : str / list of selections
        ndim : {1, 2}
            requested ndim of result
        subset : object, default None
            subset to act on
        """
        raise AbstractMethodError(self)

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Print obj.columns to verify the exact name.
  2. Strip/normalize column names at load: `df.columns = df.columns.str.strip()`.
  3. Use df.get('key') for optional access.

Example fix

// before
g = df.groupby('g')['Revenue']  # actual: 'revenue'

// after
df.columns = df.columns.str.lower().str.strip()
g = df.groupby('g')['revenue']
Defensive patterns

Strategy: validation

Validate before calling

if key not in obj.columns:
    raise KeyError(f'Column not found: {key}; available: {list(obj.columns)}')

Type guard

def column_exists(df, key) -> bool:
    return key in df.columns

Try / catch

try:
    sub = holder[key]
except KeyError as e:
    if 'Column not found' in str(e):
        candidates = [c for c in obj.columns if str(c).lower() == str(key).lower()]
        sub = holder[candidates[0]] if candidates else None
    else:
        raise

Prevention

When it happens

Trigger: `df.groupby('g')['nonexistent']`; selecting a single missing column on a SelectionMixin holder.

Common situations: Case sensitivity in column names; renamed columns; trailing whitespace in headers.

Related errors


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