pola-rs/polars · error

comparing enums with different FrozenCategories is not suppo

Error message

comparing enums with different FrozenCategories is not supported through AnyValue

What it means

PartialEq for AnyValue panics when comparing two Enum values whose FrozenCategories maps are different Arc allocations. Enum categories are fixed per dtype; two distinct map objects mean two different enum types, and the index-hashing Hash impl forbids cross-map equality, so the guard trips.

Source

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

            (List(l), List(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, _)) => struct_eq_missing(
                struct_owned_value_iter(l.as_ref()),

View on GitHub (pinned to df599052da)

Solutions

  1. Cast both enum columns to String and compare the string values
  2. Unify the enum dtype: reuse one pl.Enum([...]) dtype object (or cast one column to the other's dtype) so both sides share the same frozen categories
  3. Avoid scalar-level == on enums; compare at the Series level after aligning dtypes

Example fix

# before
ok = a["e"].get(0) == b["e"].get(0)  # two distinct Enum dtypes -> panic

# after
ok = str(a["e"].cast(pl.String).get(0)) == str(b["e"].cast(pl.String).get(0))
Defensive patterns

Strategy: validation

Validate before calling

def enum_scalars_comparable(a: pl.Series, b: pl.Series) -> bool:
    return a.dtype == b.dtype  # identical Enum dtype -> same frozen categories

Type guard

def same_enum(a: pl.Series, b: pl.Series) -> bool:
    return isinstance(a.dtype, pl.Enum) and isinstance(b.dtype, pl.Enum) and a.dtype == b.dtype

Try / catch

try:
    eq = e1 == e2
except Exception:
    eq = str(e1.cast(pl.String)) == str(e2.cast(pl.String))

Prevention

When it happens

Trigger: Comparing Enum AnyValues from columns declared with separate pl.Enum([...]) definitions (even with identical category lists), e.g. df1["e"].get(0) == df2["e"].get(0) where the enums were constructed independently.

Common situations: Reused column definitions that each construct a new pl.Enum([...]), comparing enum scalars across DataFrames or against enum literals from a different dtype instance.

Related errors


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