pola-rs/polars · error

not implemented

Error message

not implemented

What it means

The FixedSizeList take kernel gathers rows by byte-copying contiguous element buffers, so its helper get_buffer_and_size only implements PhysicalType::Primitive. Taking from a pl.Array(inner, width) column whose element type is not Arrow-primitive (String, Boolean, nested List/Struct) falls into the wildcard arm and panics 'not implemented'.

Source

Thrown at crates/polars-compute/src/gather/fixed_size_list.rs:58

fn get_leaves(array: &FixedSizeListArray) -> &dyn Array {
    if let Some(array) = array.values().as_any().downcast_ref::<FixedSizeListArray>() {
        get_leaves(array)
    } else {
        &**array.values()
    }
}

fn get_buffer_and_size(array: &dyn Array) -> (&[u8], usize) {
    match array.dtype().to_physical_type() {
        PhysicalType::Primitive(primitive) => with_match_primitive_type!(primitive, |$T| {

            let arr = array.as_any().downcast_ref::<PrimitiveArray<$T>>().unwrap();
            let values = arr.values();
            (bytemuck::cast_slice(values), size_of::<$T>())

        }),
        _ => {
            unimplemented!()
        },
    }
}

unsafe fn from_buffer(mut buf: ManuallyDrop<Vec<u8>>, dtype: &ArrowDataType) -> ArrayRef {
    match dtype.to_physical_type() {
        PhysicalType::Primitive(primitive) => with_match_primitive_type!(primitive, |$T| {
            let ptr = buf.as_mut_ptr();
            let len_units = buf.len();
            let cap_units = buf.capacity();

            let buf = Vec::from_raw_parts(
                ptr as *mut $T,
                len_units / size_of::<$T>(),
                cap_units / size_of::<$T>(),
            );

            PrimitiveArray::from_data_default(buf.into(), None).boxed()

View on GitHub (pinned to 9b5d73fd00)

Solutions

  1. Cast Array to List around the gather: s.cast(pl.List(inner)).gather(idx).cast(pl.Array(inner, width))
  2. Keep Array element types primitive in stored schemas (encode strings as fixed-size binary or id hashes)
  3. Upstream: route non-primitive FixedSizeList elements through a generic take path instead of the byte-copy fast path

Example fix

# before
s = pl.Series([["a", "b"]], dtype=pl.Array(pl.String, 2))
s.gather([0, 1])  # unimplemented: element type not primitive
# after
s.cast(pl.List(pl.String)).gather([0, 1]).cast(pl.Array(pl.String, 2))
Defensive patterns

Strategy: validation

Validate before calling

# only gather Array columns whose element dtype is primitive
PRIMITIVE = {pl.Int8, pl.Int16, pl.Int32, pl.Int64, pl.UInt8, pl.UInt16, pl.UInt32,
             pl.UInt64, pl.Float32, pl.Float64}

def array_gather_safe(s: pl.Series, idx) -> pl.Series:
    if s.dtype == pl.Array and s.dtype.inner.is_nested():
        return s.cast(pl.List(s.dtype.inner)).gather(idx).cast(s.dtype)
    return s.gather(idx)

Type guard

def is_primitive_element_array(dtype) -> bool:
    return dtype == pl.Array and not dtype.inner.is_nested() and dtype.inner != pl.Boolean

Prevention

When it happens

Trigger: Any operation lowering to gather on a FixedSizeListArray with non-primitive elements: Series.gather([..]), df[[0, 2]] row selection, filter, join reindexing, group_by output reordering - on columns like pl.Array(pl.String, 2) or pl.Array(pl.Boolean, 3).

Common situations: Embedding/vector pipelines that store fixed-size string tag arrays or boolean masks per row; code validated with pl.Array(pl.Float32, 128) (primitive, works) that is later pointed at Array(pl.String, k) and panics during a filter or join.

Related errors


AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19). Data as JSON: /api/errors/2cc2a60b9fa47370. Report an issue: GitHub.