pola-rs/polars · error

comparing enums with different FrozenCategories is not…

Error message

comparing enums with different FrozenCategories is not supported through AnyValue

What it means

AnyValue::eq_missing refuses to compare two Enum values whose FrozenCategory mappings are distinct Arc allocations. Enum's physical representation is a u32 index into its fixed FrozenCategories; equality across different FrozenCategories would compare unrelated indices. The Hash impl hashes the raw index, so the library panics with unimplemented!() rather than returning a wrong result.

Solutions

  1. Ensure both Enum columns use the same DataType::Enum definition (same categories, same order) so they share the FrozenCategories mapping
  2. Cast both columns to Str and compare the string values
  3. Cast both to their physical u32 representation only if you have verified the mappings are identical
  4. Rebuild one column with the other's Enum data type via cast to a common Enum type

Example fix

// before: two Enum columns built from separate Enum definitions
let e1 = Series::new("e1", ["a"]).unwrap().cast(&DataType::Enum(None, Arc::new(PlSmallStr::from_static("Enum1")) /* distinct FrozenCategories */)).unwrap();
let e2 = Series::new("e2", ["a"]).unwrap().cast(&DataType::Enum(None, Arc::new(PlSmallStr::from_static("Enum2")))).unwrap();
let _ = e1.equal(&e2)?; // panics: different FrozenCategories
// after: use one shared Enum data type
let dt = DataType::Enum(None, Arc::new(PlSmallStr::from_static("MyEnum")));
let e1 = Series::new("e1", ["a"]).unwrap().cast(&dt).unwrap();
let e2 = Series::new("e2", ["a"]).unwrap().cast(&dt).unwrap();
let _ = e1.equal(&e2)?;
Defensive patterns

Strategy: validation

Validate before calling

fn same_frozen_categories(a: &AnyValue, b: &AnyValue) -> bool {
    match (a, b) {
        (AnyValue::Enum(_, l), AnyValue::Enum(_, r)) => Arc::ptr_eq(l, r),
        _ => false,
    }
}

Prevention

When it happens

Trigger: Calling AnyValue::eq_missing (or eq / tot_eq) with two AnyValue::Enum variants whose FrozenRevMapping Arcs differ — e.g. Enum columns created from two different Enums declarations or built in separate processes/frames without a shared frozen mapping.

Common situations: Comparing Enum-typed columns that came from different sources or different Enum type definitions with the same logical names, joining Enum frames built from distinct DataType::Enum instantiations, or deserializing Enum data without a shared mapping.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at crates/polars-core/src/datatypes/any_value.rs:1295

            (Map(l), Map(r)) => l == r,
            #[cfg(feature = "dtype-categorical")]
            (Categorical(cat_l, map_l), Categorical(cat_r, map_r)) => {
                if !Arc::ptr_eq(map_l, map_r) {
                    // We can't support this because our Hash impl directly hashes the index. If you
                    // add support for this we must change the Hash impl.
                    unimplemented!(
                        "comparing categoricals with different Categories is not supported through AnyValue"
                    );
                }

                cat_l == cat_r
            },
            #[cfg(feature = "dtype-categorical")]
            (Enum(cat_l, map_l), Enum(cat_r, map_r)) => {
                if !Arc::ptr_eq(map_l, map_r) {
                    // We can't support this because our Hash impl directly hashes the index. If you
                    // add support for this we must change the Hash impl.
                    unimplemented!(
                        "comparing enums with different FrozenCategories is not supported through AnyValue"
                    );
                }

                cat_l == cat_r
            },
            #[cfg(feature = "dtype-duration")]
            (Duration(l, tu_l), Duration(r, tu_r)) => l == r && tu_l == tu_r,

            #[cfg(feature = "dtype-struct")]
            (StructOwned(l), StructOwned(r)) => struct_eq_missing(
                struct_owned_value_iter(l.as_ref()),
                struct_owned_value_iter(r.as_ref()),
                null_equal,
            ),
            #[cfg(feature = "dtype-struct")]
            (StructOwned(l), Struct(idx, arr, fields)) => struct_eq_missing(
                struct_owned_value_iter(l.as_ref()),

View on GitHub (pinned to fe841f959e)