pola-rs/polars · error

groups are slices not index

Error message

groups are slices not index

What it means

GroupsType is an enum with two representations: Idx (vec of first-index + all-indices) and Slice (offset/length pairs, produced by fast paths such as group_by on sorted/contiguous data). unwrap_idx() assumes the Idx representation and panics with 'groups are slices not index' when the groups are stored as slices.

Source

Thrown at crates/polars-core/src/frame/group_by/position.rs:501

                .into_iter()
                .map(|[first, len]| first + len - 1)
                .collect(),
        }
    }

    pub fn par_iter(&self) -> GroupsTypeParIter<'_> {
        GroupsTypeParIter::new(self)
    }

    /// Get a reference to the `GroupsIdx`.
    ///
    /// # Panic
    ///
    /// panics if the groups are a slice.
    pub fn unwrap_idx(&self) -> &GroupsIdx {
        match self {
            GroupsType::Idx(groups) => groups,
            GroupsType::Slice { .. } => panic!("groups are slices not index"),
        }
    }

    /// Get a reference to the `GroupsSlice`.
    ///
    /// # Panic
    ///
    /// panics if the groups are an idx.
    pub fn unwrap_slice(&self) -> &GroupsSlice {
        match self {
            GroupsType::Slice { groups, .. } => groups,
            GroupsType::Idx(_) => panic!("groups are index not slices"),
        }
    }

    pub fn get(&self, index: usize) -> GroupsIndicator<'_> {
        match self {
            GroupsType::Idx(groups) => {

View on GitHub (pinned to 68506541d2)

Solutions

  1. Match on the enum instead of unwrapping: if let GroupsType::Idx(idx) = groups { ... } else { ... }
  2. Use the Option-returning accessor groups.idx() to detect the representation before unwrapping
  3. Convert representation explicitly (GroupsType::into_idx / sort_unsliced variants) before index-only code

Example fix

// before
let idx = groups.unwrap_idx();

// after
match groups.idx() {
    Some(idx) => { /* index path */ },
    None => { /* handle GroupsType::Slice */ },
}
Defensive patterns

Strategy: type-guard

Validate before calling

let is_idx = matches!(groups, GroupsType::Idx(_));
if !is_idx { /* convert or take slice path */ }

Type guard

fn has_idx_groups(g: &GroupsType) -> bool {
    matches!(g, GroupsType::Idx(_))
}

Prevention

When it happens

Trigger: Calling GroupsType::unwrap_idx() (directly or via a helper that expects indices) on groups produced by group_by on sorted keys, unique() fast paths, or any partition operation that emits GroupsType::Slice.

Common situations: Library/extension code written against GroupsIdx that breaks when input data is sorted (which switches the engine to the slice representation); tests passing unsorted data but production hitting sorted data.

Related errors


AI-assisted analysis of pola-rs/polars@68506541d2 (2026-08-19). Data as JSON: /api/errors/600ea1e066d89984. Report an issue: GitHub.