{"record":{"id":"1a0d987520002306","repo":"pola-rs/polars","slug":"non-dictionary-categoricals-are-not-yet-supported","errorCode":null,"errorMessage":"non-dictionary categoricals are not yet supported","messagePattern":"non-dictionary categoricals are not yet supported","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/interchange/from_dataframe.py","lineNumber":150,"sourceCode":"    data = pl.Series._from_buffers(String, data=data_buffers, validity=None)\n\n    # Add the validity buffer if present\n    validity_buffer = _construct_validity_buffer(\n        buffers[\"validity\"], column, String, data, offset, allow_copy=allow_copy\n    )\n    if validity_buffer is not None:\n        data = pl.Series._from_buffers(\n            String, data=data_buffers, validity=validity_buffer\n        )\n\n    return data\n\n\ndef _categorical_column_to_series(column: Column, *, allow_copy: bool) -> Series:\n    categorical = column.describe_categorical\n    if not categorical[\"is_dictionary\"]:\n        msg = \"non-dictionary categoricals are not yet supported\"\n        raise NotImplementedError(msg)\n\n    categories_col = categorical[\"categories\"]\n    if categories_col.size() == 0:\n        dtype = Enum([])\n    elif categories_col.dtype[0] != DtypeKind.STRING:\n        msg = \"non-string categories are not supported\"\n        raise NotImplementedError(msg)\n    else:\n        categories = _string_column_to_series(categories_col, allow_copy=allow_copy)\n        dtype = Enum(categories)\n\n    buffers = column.get_buffers()\n    offset = column.offset\n\n    data_buffer = _construct_data_buffer(\n        *buffers[\"data\"], column.size(), offset, allow_copy=allow_copy\n    )\n    validity_buffer = _construct_validity_buffer(","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/pola-rs/polars/blob/9b5d73fd00236295624374b075d16b1fe6ec6df9/py-polars/src/polars/interchange/from_dataframe.py#L132-L168","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hand-written interchange adapters for in-house formats that expose 'listed' style categoricals; early-adopter interop libraries experimenting with non-dictionary encodings.","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)."],"exampleFix":"# producer side, before\n def describe_categorical(self):\n     return {\"is_dictionary\": False}  # -> NotImplementedError\n# after\n def describe_categorical(self):\n     return {\"is_dictionary\": True, \"categories\": self._categories_col}","handlingStrategy":"validation","validationCode":"def is_dictionary_categorical(col) -> bool:\n    if col.dtype[0] != DtypeKind.CATEGORICAL:\n        return True\n    return bool(col.describe_categorical().get(\"is_dictionary\"))\n\nok = all(is_dictionary_categorical(icdf.get_column(i)) for i in range(icdf.num_columns()))","typeGuard":null,"tryCatchPattern":"try:\n    df = pl.from_dataframe(obj)\nexcept NotImplementedError as e:\n    if \"non-dictionary categoricals\" not in str(e):\n        raise\n    # convert the categorical column to plain strings on the producer, then retry","preventionTips":["Encode categoricals as dictionary (indices + categories) in any custom interchange producer.","Avoid exotic categorical encodings when interoperability with Polars is required."],"tags":["polars","interchange-protocol","categorical","notimplementederror"],"backgroundTag":"categorical-interchange-unsupported","analyzedSha":"9b5d73fd00236295624374b075d16b1fe6ec6df9","analyzedAt":"2026-08-19T12:15:06.350Z","contentChangedAt":"2026-08-19T12:15:06.350Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}