pola-rs/polars · error · TypeError
`df` of type does not support the dataframe interchange…
Error message
`df` of type {qualified_type_name(df)!r} does not support the dataframe interchange protocol What it means
pl.from_dataframe() only accepts objects implementing the dataframe interchange protocol, which it detects by the presence of a __dataframe__ method (pl.DataFrame and Polars interchange wrappers are short-circuited). Anything else — numpy arrays, dicts, lists, frames from libraries without interchange support — raises this TypeError naming the qualified type. Note from_dataframe and the interchange protocol are deprecated since Polars 1.40.0.
Solutions
- Use the native constructor for the source type: pl.from_pandas(df), pl.from_arrow(tbl), or pl.from_numpy(arr, schema=...).
- For pandas sources, install/upgrade pyarrow (pip install -U pyarrow) and use pandas >= 2.0 so __dataframe__ exists.
- For pl.LazyFrame, call .collect() before conversion.
- For your own format, implement a __dataframe__ method returning a protocol-conformant object.
Example fix
# before df = pl.from_dataframe(pandas_df) # TypeError when __dataframe__ is missing # after df = pl.from_pandas(pandas_df)
Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(df, pl.LazyFrame):
df = df.collect()
elif not hasattr(df, "__dataframe__"):
if hasattr(df, "to_arrow"): # e.g. pyarrow Table
df = pl.from_arrow(df.to_arrow())
elif hasattr(df, "columns") and "pandas" in type(df).__module__:
df = pl.from_pandas(df)
else:
raise TypeError(f"cannot convert {type(df).__name__} to Polars") Type guard
from typing import Any, Protocol, TypeGuard
class SupportsInterchange(Protocol):
def __dataframe__(self, *, allow_copy: bool = True) -> Any: ...
def supports_interchange(obj: Any) -> TypeGuard[SupportsInterchange]:
return hasattr(obj, "__dataframe__") Try / catch
try:
df = pl.from_dataframe(obj)
except TypeError as e:
if "does not support the dataframe interchange protocol" not in str(e):
raise
df = pl.from_pandas(obj) if "pandas" in type(obj).__module__ else pl.from_arrow(obj) Prevention
- Prefer the type-specific constructors: pl.from_pandas / pl.from_arrow / pl.from_numpy.
- Check hasattr(obj, '__dataframe__') before calling pl.from_dataframe.
- Keep pyarrow installed and pandas >= 2.0 if you rely on interchange.
- Note the interchange API is deprecated since Polars 1.40.0 — plan a migration to Arrow-based conversion.
When it happens
Trigger: pl.from_dataframe(obj) where obj is a numpy.ndarray, dict, list, pl.LazyFrame, duckdb relation, or a pandas DataFrame whose interchange support is unavailable (pandas < 1.5, or pyarrow missing on older pandas).
Common situations: Expecting from_dataframe to be a universal converter and passing numpy arrays or dicts; passing a pl.LazyFrame instead of .collect()-ing it; using pandas without pyarrow installed so pandas.DataFrame has no __dataframe__; migrating code after the 1.40 deprecation of the interchange protocol.
Related errors
- invalid sentinel value for column of type
- pandas>=1.5.0 is required for…
- pyarrow>=8.0.0 is required for…
- pyarrow is required for converting a pandas dataframe to…
- pyarrow is required for converting a pandas series to…
AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19).
Data as JSON: /api/errors/036eeae7fba884f2.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/interchange/from_dataframe.py:52
Support for the Dataframe Interchange Protocol is deprecated.
Parameters
----------
df
Object supporting the dataframe interchange protocol, i.e. must have implemented
the `__dataframe__` method.
allow_copy
Allow memory to be copied to perform the conversion. If set to False, causes
conversions that are not zero-copy to fail.
"""
if isinstance(df, pl.DataFrame):
return df
elif isinstance(df, PolarsDataFrame):
return df._df
if not hasattr(df, "__dataframe__"):
msg = f"`df` of type {qualified_type_name(df)!r} does not support the dataframe interchange protocol"
raise TypeError(msg)
return _from_dataframe(
df.__dataframe__(allow_copy=allow_copy), # type: ignore[arg-type]
allow_copy=allow_copy,
)
def _from_dataframe(df: InterchangeDataFrame, *, allow_copy: bool) -> DataFrame:
chunks = []
for chunk in df.get_chunks():
polars_chunk = _protocol_df_chunk_to_polars(chunk, allow_copy=allow_copy)
chunks.append(polars_chunk)
# Handle implementations that incorrectly yield no chunks for an empty dataframe
if not chunks:
polars_chunk = _protocol_df_chunk_to_polars(df, allow_copy=allow_copy)
chunks.append(polars_chunk)
View on GitHub (pinned to 9b5d73fd00)