pola-rs/polars · error

can't order enums from different FrozenCategories

Error message

can't order enums from different FrozenCategories

What it means

AnyValue::partial_cmp panics when ordering two Enum values backed by different FrozenCategories maps. Unlike Categorical (which falls back to comparing category strings), enum ordering is defined by category position within one frozen list, so a cross-map comparison has no meaning and is rejected.

Source

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

            (Duration(lt, lu), Duration(rt, ru)) => {
                if lu != ru {
                    unimplemented!("comparing durations with different units is not supported");
                }

                lt.partial_cmp(rt)
            },
            #[cfg(feature = "dtype-time")]
            (Time(l), Time(r)) => l.partial_cmp(r),
            #[cfg(feature = "dtype-categorical")]
            (Categorical(l_cat, l_map), Categorical(r_cat, r_map)) => unsafe {
                let l_str = l_map.cat_to_str_unchecked(*l_cat);
                let r_str = r_map.cat_to_str_unchecked(*r_cat);
                l_str.partial_cmp(r_str)
            },
            #[cfg(feature = "dtype-categorical")]
            (Enum(l_cat, l_map), Enum(r_cat, r_map)) => {
                if !Arc::ptr_eq(l_map, r_map) {
                    unimplemented!("can't order enums from different FrozenCategories")
                }
                l_cat.partial_cmp(r_cat)
            },
            (List(_), List(_)) => {
                unimplemented!("ordering for List dtype is not supported")
            },
            #[cfg(feature = "dtype-array")]
            (Array(..), Array(..)) => {
                unimplemented!("ordering for Array dtype is not supported")
            },
            #[cfg(feature = "object")]
            (Object(_), Object(_)) => {
                unimplemented!("ordering for Object dtype is not supported")
            },
            #[cfg(feature = "dtype-struct")]
            (StructOwned(_), StructOwned(_))
            | (StructOwned(_), Struct(..))
            | (Struct(..), StructOwned(_))

View on GitHub (pinned to df599052da)

Solutions

  1. Cast to String before ordering when you want lexicographic order of the category names
  2. Unify the enum dtype first (cast one column to the other's pl.Enum dtype) so both values share one frozen map and positional ordering applies
  3. Avoid scalar-level ordering of enums; sort the Series after aligning dtypes

Example fix

# before
m = min(a["e"].get(0), b["e"].get(0))  # different Enum maps -> panic

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

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try:
    m = min(e1, e2)
except Exception:
    m = min(str(e1.cast(pl.String)), str(e2.cast(pl.String)))

Prevention

When it happens

Trigger: Sorting or comparing (<, >, min/max) Enum AnyValues from two separately constructed pl.Enum dtypes: sorted([a["e"].get(0), b["e"].get(0)]) where the two enum columns have independent category definitions.

Common situations: Merging or ranking values from frames whose enum columns were declared independently, or mixing 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/60417628434af9fa. Report an issue: GitHub.