pola-rs/polars · error · NotImplementedError
unsupported null type
Error message
unsupported null type: {null_type!r} What it means
Polars' interchange importer understands exactly four null representations: USE_BITMAP, USE_BYTEMASK, USE_NAN, and USE_SENTINEL. If a column's describe_null() reports any other ColumnNullType (including None or constants from newer protocol revisions), NotImplementedError('unsupported null type: ...') is raised.
Solutions
- Upgrade Polars to a version that knows the null type.
- Fix the producer to report one of USE_BITMAP/USE_BYTEMASK/USE_NAN/USE_SENTINEL (or no nulls at all).
- Convert via pyarrow or the producer's native export path instead of the interchange protocol.
Example fix
# producer side, before
def describe_null(self):
return (None, None) # -> NotImplementedError
# after
def describe_null(self):
return (ColumnNullType.USE_BITMAP, 0) Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED_NULL_TYPES = {
ColumnNullType.USE_BITMAP,
ColumnNullType.USE_BYTEMASK,
ColumnNullType.USE_NAN,
ColumnNullType.USE_SENTINEL,
}
unsupported = [
i for i in range(icdf.num_columns())
if icdf.get_column(i).describe_null()[0] not in SUPPORTED_NULL_TYPES
] Try / catch
try:
df = pl.from_dataframe(obj)
except NotImplementedError as e:
if "unsupported null type" not in str(e):
raise
# upgrade Polars, or fix the producer's describe_null() to a supported constant Prevention
- Pin producer and consumer protocol versions together; upgrade both in lockstep.
- Return one of the four supported null types (or no-nulls) from describe_null().
When it happens
Trigger: pl.from_dataframe(obj) where describe_null()[0] is outside the four supported values — a buggy producer returning None/0, or a producer built against a newer protocol revision that added a null type this Polars version does not know.
Common situations: Version skew: producer library newer than the installed Polars; custom interchange implementations returning a placeholder; producers using the protocol's NONNULL constant incorrectly (it must be handled before buffers are requested).
Related errors
- non-dictionary categoricals are not yet supported
- non-string categories are not supported
- unsupported data type
- unsupported temporal data type
- bitmask must be constructed
AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19).
Data as JSON: /api/errors/1b7b7a8895eeca28.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/interchange/from_dataframe.py:295
return data.is_not_nan()
elif null_type == ColumnNullType.USE_SENTINEL:
if not allow_copy:
msg = "bitmask must be constructed"
raise CopyNotAllowedError(msg)
sentinel = pl.Series([null_value])
try:
if column_dtype.is_temporal():
sentinel = sentinel.cast(column_dtype)
return data != sentinel # noqa: TRY300
except InvalidOperationError as e:
msg = f"invalid sentinel value for column of type {column_dtype}: {null_value!r}"
raise TypeError(msg) from e
else:
msg = f"unsupported null type: {null_type!r}"
raise NotImplementedError(msg)
def _construct_validity_buffer_from_bitmask(
buffer: Buffer,
null_value: int,
length: int,
offset: int = 0,
*,
allow_copy: bool,
) -> Series:
buffer_info = (buffer.ptr, offset, length)
s = pl.Series._from_buffer(Boolean, buffer_info, buffer)
if null_value != 0:
if not allow_copy:
msg = "bitmask must be inverted"
raise CopyNotAllowedError(msg)
s = ~sView on GitHub (pinned to 9b5d73fd00)