pola-rs/polars · error

not implemented

Error message

not implemented

What it means

equal(lhs, rhs) implements == for dyn Scalar: it first compares dtypes (mismatched dtypes return false without panicking) and then dispatches on physical type. Arms exist for Null, Boolean, all primitives, LargeUtf8/LargeBinary/LargeList, dictionaries, structs, FixedSizeBinary/List, union, map and Utf8View — but the 32-bit Utf8 and Binary physical types and BinaryView are missing, so they fall into _ => unimplemented!() (crates/polars-arrow/src/scalar/equal.rs:56) and panic instead of returning a bool.

Source

Thrown at crates/polars-arrow/src/scalar/equal.rs:56

    match lhs.dtype().to_physical_type() {
        Null => dyn_eq!(NullScalar, lhs, rhs),
        Boolean => dyn_eq!(BooleanScalar, lhs, rhs),
        Primitive(primitive) => with_match_primitive_type_full!(primitive, |$T| {
            dyn_eq!(PrimitiveScalar<$T>, lhs, rhs)
        }),
        LargeUtf8 => dyn_eq!(Utf8Scalar<i64>, lhs, rhs),
        LargeBinary => dyn_eq!(BinaryScalar<i64>, lhs, rhs),
        LargeList => dyn_eq!(ListScalar<i64>, lhs, rhs),
        Dictionary(key_type) => match_integer_type!(key_type, |$T| {
            dyn_eq!(DictionaryScalar<$T>, lhs, rhs)
        }),
        Struct => dyn_eq!(StructScalar, lhs, rhs),
        FixedSizeBinary => dyn_eq!(FixedSizeBinaryScalar, lhs, rhs),
        FixedSizeList => dyn_eq!(FixedSizeListScalar, lhs, rhs),
        Union => dyn_eq!(UnionScalar, lhs, rhs),
        Map => dyn_eq!(MapScalar, lhs, rhs),
        Utf8View => dyn_eq!(BinaryViewScalar<str>, lhs, rhs),
        _ => unimplemented!(),
    }
}

View on GitHub (pinned to df599052da)

Solutions

  1. Cast the column to LargeUtf8/Utf8View (or BinaryView) before extracting scalars — those arms are implemented
  2. Downcast and compare the concrete scalar types yourself (Utf8Scalar<i32> implements PartialEq natively)
  3. Guard on to_physical_type() before comparing dyn scalars
  4. Add the missing arms upstream, mirroring the LargeUtf8 arm with Utf8Scalar<i32>, BinaryScalar<i32> and BinaryViewScalar<[u8]>

Example fix

// before
let eq = lhs_scalar == rhs_scalar; // panics for Utf8 scalars

// after
let eq = match lhs_scalar.dtype().to_physical_type() {
    PhysicalType::Utf8 => {
        let l = lhs_scalar.as_any().downcast_ref::<Utf8Scalar<i32>>().unwrap();
        let r = rhs_scalar.as_any().downcast_ref::<Utf8Scalar<i32>>().unwrap();
        l == r
    },
    _ => lhs_scalar == rhs_scalar,
};
Defensive patterns

Strategy: type-guard

Validate before calling

if !scalar_eq_supported(lhs.dtype()) {
    polars_bail!(InvalidOperation: "scalar equality not implemented for {:?}; cast to Utf8View/LargeUtf8 first", lhs.dtype());
}

Type guard

fn scalar_eq_supported(dtype: &ArrowDataType) -> bool {
    use polars_arrow::datatypes::PhysicalType::*;
    !matches!(dtype.to_physical_type(), Utf8 | Binary | BinaryView)
}

Try / catch

let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| lhs_scalar == rhs_scalar));
let eq = match res {
    Ok(v) => v,
    Err(_) => polars_bail!(ComputeError: "scalar comparison panicked: cast Utf8/Binary to Utf8View first"),
};

Prevention

When it happens

Trigger: Comparing Box<dyn Scalar>/Arc<dyn Scalar> values whose dtype is Utf8 (i32 offsets), Binary (i32) or BinaryView — e.g. scalar == scalar in expression evaluation, filter predicates, or tests after extracting .get(0)/scalar() from legacy string/binary arrays.

Common situations: Older IPC/Parquet string data still in Utf8/Binary (i32) form; scalars pulled from arrays before a cast to Utf8View; hand-written equality helpers over dyn Scalar in join or predicate code.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/8e345c0f90c9bd0b. Report an issue: GitHub.