pola-rs/polars · error · NotImplementedError

non-dictionary categoricals are not yet supported

Error message

non-dictionary categoricals are not yet supported

What it means

The interchange protocol lets a producer declare categorical columns as dictionary-encoded (is_dictionary=True) or another encoding. Polars only implements dictionary-encoded categoricals (indices buffer + categories column); when describe_categorical()['is_dictionary'] is False it raises NotImplementedError rather than guessing an encoding.

Solutions

  1. On the producer side, encode the column as a dictionary (indices + categories) or export it as plain strings.
  2. Convert the categorical column to string before handing the frame to Polars.
  3. If you control neither side, catch NotImplementedError for that column and convert it through an alternative path (e.g. pyarrow).

Example fix

# producer side, before
 def describe_categorical(self):
     return {"is_dictionary": False}  # -> NotImplementedError
# after
 def describe_categorical(self):
     return {"is_dictionary": True, "categories": self._categories_col}
Defensive patterns

Strategy: validation

Validate before calling

def is_dictionary_categorical(col) -> bool:
    if col.dtype[0] != DtypeKind.CATEGORICAL:
        return True
    return bool(col.describe_categorical().get("is_dictionary"))

ok = all(is_dictionary_categorical(icdf.get_column(i)) for i in range(icdf.num_columns()))

Try / catch

try:
    df = pl.from_dataframe(obj)
except NotImplementedError as e:
    if "non-dictionary categoricals" not in str(e):
        raise
    # convert the categorical column to plain strings on the producer, then retry

Prevention

When it happens

Trigger: pl.from_dataframe(obj) where a CATEGORICAL-kind column's describe_categorical() returns is_dictionary=False — only seen with custom interchange producers or experimental libraries; mainstream producers (pyarrow dictionary type, pandas categorical) always use dictionary encoding.

Common situations: Hand-written interchange adapters for in-house formats that expose 'listed' style categoricals; early-adopter interop libraries experimenting with non-dictionary encodings.

Related errors


AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19). Data as JSON: /api/errors/1a0d987520002306. Report an issue: GitHub.

Appendix: source

Thrown at py-polars/src/polars/interchange/from_dataframe.py:150

    data = pl.Series._from_buffers(String, data=data_buffers, validity=None)

    # Add the validity buffer if present
    validity_buffer = _construct_validity_buffer(
        buffers["validity"], column, String, data, offset, allow_copy=allow_copy
    )
    if validity_buffer is not None:
        data = pl.Series._from_buffers(
            String, data=data_buffers, validity=validity_buffer
        )

    return data


def _categorical_column_to_series(column: Column, *, allow_copy: bool) -> Series:
    categorical = column.describe_categorical
    if not categorical["is_dictionary"]:
        msg = "non-dictionary categoricals are not yet supported"
        raise NotImplementedError(msg)

    categories_col = categorical["categories"]
    if categories_col.size() == 0:
        dtype = Enum([])
    elif categories_col.dtype[0] != DtypeKind.STRING:
        msg = "non-string categories are not supported"
        raise NotImplementedError(msg)
    else:
        categories = _string_column_to_series(categories_col, allow_copy=allow_copy)
        dtype = Enum(categories)

    buffers = column.get_buffers()
    offset = column.offset

    data_buffer = _construct_data_buffer(
        *buffers["data"], column.size(), offset, allow_copy=allow_copy
    )
    validity_buffer = _construct_validity_buffer(

View on GitHub (pinned to 9b5d73fd00)