pola-rs/polars · error · ValueError
data type not supported by the interchange protocol
Error message
data type {dtype!r} not supported by the interchange protocol What it means
When a Polars DataFrame is exported through the dataframe interchange protocol, each column's dtype is mapped via a fixed lookup table covering primitives (bool, ints, floats), String, Date, Datetime, Duration, Categorical and Enum. Any dtype outside that table — nested types (List, Struct, Array), Binary, Object, Null, Decimal, Time — raises ValueError('data type ... not supported by the interchange protocol').
Solutions
- Drop or stringify unsupported columns before interchange: df.select(pl.col('nested').cast(pl.String)) or .drop('nested').
- Use the Arrow path for nested data: df.write_arrow / pl.from_arrow, which supports List and Struct natively.
- If the consumer supports it, serialize nested columns to JSON strings and decode after transfer.
Example fix
# before
icdf = df.__dataframe__() # List/Struct/Object column -> ValueError
# after
df_flat = df.with_columns(pl.col("payload").cast(pl.String)) # or .drop("payload")
icdf = df_flat.__dataframe__() Defensive patterns
Strategy: validation
Validate before calling
INTERCHANGE_SUPPORTED = {
pl.Boolean, pl.Int8, pl.Int16, pl.Int32, pl.Int64,
pl.UInt8, pl.UInt16, pl.UInt32, pl.UInt64,
pl.Float32, pl.Float64, pl.String, pl.Date,
pl.Datetime, pl.Duration, pl.Categorical, pl.Enum,
}
unsupported = [
name for name, dtype in df.schema.items()
if dtype.base_type() not in INTERCHANGE_SUPPORTED
]
export_df = df.drop(unsupported) if unsupported else df
icdf = export_df.__dataframe__() Type guard
def interchange_safe(df: pl.DataFrame) -> bool:
nested_or_exotic = {pl.List, pl.Struct, pl.Array, pl.Object, pl.Binary, pl.Null}
return all(dt.base_type() not in nested_or_exotic for dt in df.schema.values()) Prevention
- Flatten or stringify nested columns (List/Struct/Array) before interchange export.
- Avoid Object columns entirely; cast them to String early in the pipeline.
- Use the Arrow path (to_arrow/from_arrow) when nested types must cross library boundaries.
When it happens
Trigger: An interchange consumer (another library calling df.__dataframe__()) inspects a Polars DataFrame containing List/Struct/Array/Object/Binary columns; also selecting such columns before exporting via the protocol. The Datetime/Duration entries are special-cased afterward for time unit and time zone.
Common situations: Feeding nested Polars data to interchange-only consumers; ML/interop tools that only speak the interchange protocol; mixed frames where one Object column (from .to_objects or Python objects) breaks the whole export.
Related errors
- `n_chunks` must be a multiple of the number of chunks of…
- unsupported data type
- activate dtype
- activate feature dtype-duration
- bitmask must be constructed
AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19).
Data as JSON: /api/errors/31416330151aee5a.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/interchange/utils.py:65
Float64: (DtypeKind.FLOAT, 64, "g", NE),
Boolean: (DtypeKind.BOOL, 1, "b", NE),
String: (DtypeKind.STRING, 8, "U", NE),
Date: (DtypeKind.DATETIME, 32, "tdD", NE),
Time: (DtypeKind.DATETIME, 64, "ttu", NE),
Datetime: (DtypeKind.DATETIME, 64, "tsu:", NE),
Duration: (DtypeKind.DATETIME, 64, "tDu", NE),
Categorical: (DtypeKind.CATEGORICAL, 32, "I", NE),
Enum: (DtypeKind.CATEGORICAL, 32, "I", NE),
}
def polars_dtype_to_dtype(dtype: PolarsDataType) -> Dtype:
"""Convert Polars data type to interchange protocol data type."""
try:
result = polars_dtype_to_dtype_map[dtype.base_type()]
except KeyError as exc:
msg = f"data type {dtype!r} not supported by the interchange protocol"
raise ValueError(msg) from exc
# Handle instantiated data types
if isinstance(dtype, Datetime):
return _datetime_to_dtype(dtype)
elif isinstance(dtype, Duration):
return _duration_to_dtype(dtype)
return result
def _datetime_to_dtype(dtype: Datetime) -> Dtype:
tu = dtype.time_unit[0]
tz = dtype.time_zone if dtype.time_zone is not None else ""
arrow_c_type = f"ts{tu}:{tz}"
return DtypeKind.DATETIME, 64, arrow_c_type, NE
def _duration_to_dtype(dtype: Duration) -> Dtype:View on GitHub (pinned to 9b5d73fd00)