pola-rs/polars · error · NotImplementedError

non-dictionary categoricals are not yet supported

Error message

non-dictionary categoricals are not yet supported

What it means

Polars can only import categorical columns that are dictionary-encoded, i.e. describe_categorical()['is_dictionary'] is True. A producer reporting is_dictionary=False advertises a categorical without a categories dictionary, which has no Polars equivalent on the import path, so Polars raises NotImplementedError instead of guessing.

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 df599052da)

Solutions

  1. Change the producer to dictionary-encode the column and report is_dictionary=True
  2. Expose the column as plain string or integer data instead of categorical
  3. Convert the column upstream (e.g. cast to string in the source system) before interchange conversion
Defensive patterns

Strategy: validation

Validate before calling

def categorical_columns_are_dictionary_encoded(df) -> bool:
    from polars.interchange.protocol import DtypeKind
    proto = df.__dataframe__(allow_copy=False)
    for col in proto.get_columns():
        if col.dtype[0] == DtypeKind.CATEGORICAL:
            if not col.describe_categorical()['is_dictionary']:
                return False
    return True

Try / catch

try:
    out = pl.from_dataframe(df)
except NotImplementedError as e:
    if 'non-dictionary categoricals' in str(e):
        # ask producer for plain strings or fix its encoding
        raise
    raise

Prevention

When it happens

Trigger: Consuming a categorical column from a producer whose describe_categorical() returns is_dictionary=False.

Common situations: Custom producers exposing non-dictionary categorical systems; early adopters of extended interchange features; porting pandas.Categorical-like semantics where the mapping is implicit rather than dictionary-encoded.

Related errors


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