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
- On the producer side, encode the column as a dictionary (indices + categories) or export it as plain strings.
- Convert the categorical column to string before handing the frame to Polars.
- 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
- Encode categoricals as dictionary (indices + categories) in any custom interchange producer.
- Avoid exotic categorical encodings when interoperability with Polars is required.
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
- non-string categories are not supported
- data buffer must be cast from
- unsupported data type
- unsupported null type
- unsupported temporal data type
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)