pola-rs/polars · error · NotImplementedError

conversion of polars data type

Error message

conversion of polars data type {dtype!r} to FFI not implemented

What it means

dtype_to_ffiname maps a Polars dtype to an FFI function-name suffix via DataTypeMappings.DTYPE_TO_FFINAME; unknown dtypes raise NotImplementedError. It surfaces when polars' Arrow/FFI interchange layer (get_ffi_func) has no C-API function for the dtype.

Solutions

  1. Convert via Arrow buffers instead: use Series.to_arrow() and let pyarrow handle the type.
  2. Cast to a supported physical dtype first, e.g. s.cast(pl.UInt32) for categorical-like data.
  3. Upgrade polars — newer releases add more DTYPE_TO_FFINAME entries.

Example fix

// before
get_ffi_func("...", s.dtype, s)   # NotImplementedError for pl.Enum
// after
pa_array = s.to_arrow()  # use Arrow interchange instead of FFI name lookup
Defensive patterns

Strategy: fallback

Validate before calling

from polars.datatypes.convert import dtype_to_ffiname
def ffi_supported(dtype) -> bool:
    try:
        dtype_to_ffiname(dtype)
        return True
    except NotImplementedError:
        return False

Try / catch

try:
    func = get_ffi_func(name, dtype, series)
except NotImplementedError:
    pa_array = series.to_arrow()  # Arrow interchange fallback

Prevention

When it happens

Trigger: Calling low-level FFI-based interop (e.g. polars interchange with pyarrow via __arrow_c_array__ paths or internal get_ffi_func) with a dtype lacking a mapping — nested/exotic types like pl.Enum on older versions, pl.Categorical (old), pl.Object, custom extension dtypes.

Common situations: Bridging polars data into pyarrow/other libraries through FFI helpers; custom extension dtypes that were never mapped; version skew where a new dtype predates the FFI mapping.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/bacfaa569283f0e7. Report an issue: GitHub.

Appendix: source

Thrown at py-polars/src/polars/datatypes/convert.py:269

            str_repr: obj
            for obj in globals().values()
            if is_polars_dtype(obj)
            and (str_repr := _dtype_str_repr_safe(obj)) is not None
        }


# Initialize once (poor man's singleton :)
DataTypeMappings: Final[_DataTypeMappings] = _DataTypeMappings()


def dtype_to_ffiname(dtype: PolarsDataType) -> str:
    """Return FFI function name associated with the given Polars dtype."""
    try:
        dtype = dtype.base_type()
        return DataTypeMappings.DTYPE_TO_FFINAME[dtype]
    except KeyError:  # pragma: no cover
        msg = f"conversion of polars data type {dtype!r} to FFI not implemented"
        raise NotImplementedError(msg) from None


def dtype_to_py_type(dtype: PolarsDataType) -> PythonDataType:
    """Convert a Polars dtype to a Python dtype."""
    try:
        dtype = dtype.base_type()
        return DataTypeMappings.DTYPE_TO_PY_TYPE[dtype]
    except KeyError:  # pragma: no cover
        msg = f"conversion of polars data type {dtype!r} to Python type not implemented"
        raise NotImplementedError(msg) from None


def py_type_to_arrow_type(dtype: PythonDataType) -> pa.DataType:
    """Convert a Python dtype to an Arrow dtype."""
    try:
        return DataTypeMappings.PY_TYPE_TO_ARROW_TYPE[dtype]
    except KeyError:  # pragma: no cover
        msg = f"cannot parse Python data type {dtype!r} into Arrow data type"

View on GitHub (pinned to fe841f959e)