{"record":{"id":"31416330151aee5a","repo":"pola-rs/polars","slug":"data-type-dtype-r-not-supported-by-the-interchan","errorCode":null,"errorMessage":"data type {dtype!r} not supported by the interchange protocol","messagePattern":"data type (.+?) not supported by the interchange protocol","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/interchange/utils.py","lineNumber":65,"sourceCode":"    Float64: (DtypeKind.FLOAT, 64, \"g\", NE),\n    Boolean: (DtypeKind.BOOL, 1, \"b\", NE),\n    String: (DtypeKind.STRING, 8, \"U\", NE),\n    Date: (DtypeKind.DATETIME, 32, \"tdD\", NE),\n    Time: (DtypeKind.DATETIME, 64, \"ttu\", NE),\n    Datetime: (DtypeKind.DATETIME, 64, \"tsu:\", NE),\n    Duration: (DtypeKind.DATETIME, 64, \"tDu\", NE),\n    Categorical: (DtypeKind.CATEGORICAL, 32, \"I\", NE),\n    Enum: (DtypeKind.CATEGORICAL, 32, \"I\", NE),\n}\n\n\ndef polars_dtype_to_dtype(dtype: PolarsDataType) -> Dtype:\n    \"\"\"Convert Polars data type to interchange protocol data type.\"\"\"\n    try:\n        result = polars_dtype_to_dtype_map[dtype.base_type()]\n    except KeyError as exc:\n        msg = f\"data type {dtype!r} not supported by the interchange protocol\"\n        raise ValueError(msg) from exc\n\n    # Handle instantiated data types\n    if isinstance(dtype, Datetime):\n        return _datetime_to_dtype(dtype)\n    elif isinstance(dtype, Duration):\n        return _duration_to_dtype(dtype)\n\n    return result\n\n\ndef _datetime_to_dtype(dtype: Datetime) -> Dtype:\n    tu = dtype.time_unit[0]\n    tz = dtype.time_zone if dtype.time_zone is not None else \"\"\n    arrow_c_type = f\"ts{tu}:{tz}\"\n    return DtypeKind.DATETIME, 64, arrow_c_type, NE\n\n\ndef _duration_to_dtype(dtype: Duration) -> Dtype:","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/interchange/utils.py#L47-L83","documentation":"On the export side (Polars DataFrame exposed through the interchange protocol), polars_dtype_to_dtype maps Polars dtypes to protocol dtype tuples via a lookup map. Types with no protocol representation - nested types (List, Struct, Array), Binary, Time, Null, Object - hit a KeyError that is re-raised as ValueError. Only primitive numeric, boolean, string, datetime, date, duration, categorical and enum types can be exported.","triggerScenarios":"Calling df.__dataframe__() on a Polars DataFrame, or passing one to another library's interchange consumer, when the frame contains List/Struct/Array/Binary/Null/Object/Time columns.","commonSituations":"Feeding polars output into interchange-based consumers (older ibis, vaex, plotting tools); schema drift after group_by/agg/window operations that silently produce List columns; concat growing Null-typed columns.","solutions":["Select or drop unsupported columns before conversion: df.select([c for c, d in zip(df.columns, df.dtypes) if is_exportable(d)])","Cast nested columns to a representable form first (e.g. List -> String via str serialization, or explode them)","Transfer the data with Arrow instead (df.to_arrow()), which supports nested types, instead of the deprecated interchange path"],"exampleFix":"// before\ndf.__dataframe__()  # contains List column -> ValueError\n\n// after\nexportable = [name for name, dtype in zip(df.columns, df.dtypes) if dtype.is_integer() or dtype.is_float() or dtype == pl.String or dtype.is_temporal() or dtype == pl.Boolean or dtype in (pl.Categorical, pl.Enum)]\ndf.select(exportable).__dataframe__()","handlingStrategy":"validation","validationCode":"import polars as pl\nfrom polars.interchange.utils import polars_dtype_to_dtype\n\ndef exportable_columns(df: pl.DataFrame) -> list[str]:\n    names = []\n    for name, dtype in zip(df.columns, df.dtypes):\n        try:\n            polars_dtype_to_dtype(dtype)\n        except ValueError:\n            continue\n        names.append(name)\n    return names\n\n# usage: df.select(exportable_columns(df)).__dataframe__()","typeGuard":"import polars as pl\nfrom polars.interchange.utils import polars_dtype_to_dtype\n\ndef dtype_is_interchange_exportable(dtype: pl.DataType) -> bool:\n    \"\"\"True if polars_dtype_to_dtype(dtype) succeeds.\"\"\"\n    try:\n        polars_dtype_to_dtype(dtype)\n    except ValueError:\n        return False\n    return True","tryCatchPattern":"try:\n    proto = df.__dataframe__()\nexcept ValueError as e:\n    if 'not supported by the interchange protocol' in str(e):\n        raise ValueError(\n            f'frame has non-exportable dtypes: {df.schema}'\n        ) from e\n    raise","preventionTips":["Filter frames to primitive dtypes (numeric, boolean, string, temporal, categorical/enum) before interchange export","Watch for List/Struct columns introduced by aggregations - explode or cast them first","Prefer Arrow (df.to_arrow()) when nested, Binary, Null, Object, or Time columns must be transferred"],"tags":["polars","interchange-protocol","dtype","export","value-error"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}