pola-rs/polars · error · KeyError

{key}

Error message

{key}

What it means

KeyError raised by a Categorical's CategoriesMapping.__getitem__ when a string key is not present among the category values. Polars categories form a fixed string-to-code mapping, so looking up an unseen string cannot return a code and the raw key is re-raised as the KeyError payload.

Source

Thrown at py-polars/src/polars/datatypes/classes.py:846

        phys = self._categories.physical()
        if phys == "u8":
            return pldt.UInt8
        elif phys == "u16":
            return pldt.UInt16
        elif phys == "u32":
            return pldt.UInt32
        else:
            msg = "unknown physical dtype"
            raise RuntimeError(msg)

    def is_global(self) -> bool:
        """Returns whether this refers to the global categories."""
        return self._categories.is_global()

    def __getitem__(self, key: str | int) -> str | int:
        if isinstance(key, str):
            if (cat := self._categories.get_cat(key)) is None:
                raise KeyError(key)
            return cat
        elif isinstance(key, int):
            if (s := self._categories.cat_to_str(key)) is None:
                msg = f"category index out of range: {key}"
                raise IndexError(msg)
            return s
        else:
            msg = f"invalid key type {type(key)}; expected str or int"
            raise TypeError(msg)

    def __contains__(self, item: str | int) -> bool:
        if isinstance(item, str):
            return self._categories.get_cat(item) is not None
        elif isinstance(item, int):
            return self._categories.cat_to_str(item) is not None
        else:
            return False

View on GitHub (pinned to 68506541d2)

Solutions

  1. Check membership first: 'key' in mapping (the class defines __contains__)
  2. Use mapping.get_cat(key) which returns None instead of raising
  3. Recode or build the union of categories (cat.union, Categorical full/lexical ordering setup) before cross-column lookups

Example fix

# before
code = dtype.categories['unknown_label']
# after
code = dtype.categories.get_cat('unknown_label')
if code is None:
    ...  # handle missing category
Defensive patterns

Strategy: validation

Validate before calling

if dtype.categories.get_cat(name) is None:
    raise KeyError(f'{name} not a category')

Type guard

def is_category(dtype: pl.DataType, name: str) -> bool:
    cats = getattr(getattr(dtype, 'categories', None), '_categories', None)
    return cats is not None and cats.get_cat(name) is not None

Try / catch

try:
    code = dtype.categories[name]
except KeyError:
    code = None  # unseen category

Prevention

When it happens

Trigger: Accessing categories_mapping['missing'] (or the mapping object returned by a Categorical dtype's categories) with a string that was never registered as a category, e.g. after filtering or on a categorical built from a different vocabulary.

Common situations: Comparing vocabularies across two categorical columns; interactive inspection of category mappings after slice/filter operations; typos in category lookups.

Related errors


AI-assisted analysis of pola-rs/polars@68506541d2 (2026-08-28). Data as JSON: /api/errors/f553d6465b45bbaa. Report an issue: GitHub.