pola-rs/polars · error · NotImplementedError
non-string categories are not supported
Error message
non-string categories are not supported
What it means
The categories of a dictionary-encoded categorical column must be strings. When the categories column's dtype kind is not DtypeKind.STRING (for example integer category codes), Polars cannot build the Enum type it uses for interchange categoricals and raises NotImplementedError. An empty categories column is accepted and maps to Enum([]).
Source
Thrown at py-polars/src/polars/interchange/from_dataframe.py:157
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(
buffers["validity"], column, dtype, data_buffer, offset, allow_copy=allow_copy
)
# First construct a physical Series without categories
# to allow for sentinel values that do not fit in UInt32
data_dtype = data_buffer.dtype
out = pl.Series._from_buffers(View on GitHub (pinned to df599052da)
Solutions
- Make the producer expose string categories (cast integer codes to their string labels at the source)
- Import the column as plain integers and apply the mapping in Polars afterwards with cast to Enum(['a','b',...]) using the known category list
Example fix
// before
# producer exposes integer category codes -> NotImplementedError
pl.from_dataframe(producer_df)
// after
# import codes as integers, map to Enum in polars
df = pl.from_dataframe(producer_df_without_categorical)
df = df.with_columns(pl.col('code').cast(pl.Enum(['foo', 'bar', 'baz']))) Defensive patterns
Strategy: validation
Validate before calling
def categories_are_strings(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:
cats = col.describe_categorical()['categories']
if cats.size() > 0 and cats.dtype[0] != DtypeKind.STRING:
return False
return True Try / catch
try:
out = pl.from_dataframe(df)
except NotImplementedError as e:
if 'non-string categories' in str(e):
out = pl.from_dataframe(df_without_categorical_col) # import raw codes
out = out.with_columns(pl.col('code').cast(known_enum))
else:
raise Prevention
- Expose string labels, not integer codes, as categories in producers
- Keep the code-to-label mapping on the consumer side when producers can only emit integer codes
- Test categorical round-trips with integer-keyed vocabularies explicitly
When it happens
Trigger: Dictionary-encoded column whose describe_categorical()['categories'].dtype[0] is not DtypeKind.STRING (e.g. INT category keys from the producer).
Common situations: Producers that store label-encoded vocabularies with integer keys (ML feature stores, database ENUM types with numeric codes); mapping legacy categorical encodings into polars.
Related errors
- non-dictionary categoricals are not yet supported
- `describe_categorical` only works on categorical columns
- data buffer must be cast from {data_dtype} to UInt32
- unsupported null type: {null_type!r}
- unsupported data type: {dtype!r}
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/e059529f9f26b9fc.
Report an issue: GitHub.