{"record":{"id":"600ea1e066d89984","repo":"pola-rs/polars","slug":"groups-are-slices-not-index","errorCode":null,"errorMessage":"groups are slices not index","messagePattern":"groups are slices not index","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/polars-core/src/frame/group_by/position.rs","lineNumber":501,"sourceCode":"                .into_iter()\n                .map(|[first, len]| first + len - 1)\n                .collect(),\n        }\n    }\n\n    pub fn par_iter(&self) -> GroupsTypeParIter<'_> {\n        GroupsTypeParIter::new(self)\n    }\n\n    /// Get a reference to the `GroupsIdx`.\n    ///\n    /// # Panic\n    ///\n    /// panics if the groups are a slice.\n    pub fn unwrap_idx(&self) -> &GroupsIdx {\n        match self {\n            GroupsType::Idx(groups) => groups,\n            GroupsType::Slice { .. } => panic!(\"groups are slices not index\"),\n        }\n    }\n\n    /// Get a reference to the `GroupsSlice`.\n    ///\n    /// # Panic\n    ///\n    /// panics if the groups are an idx.\n    pub fn unwrap_slice(&self) -> &GroupsSlice {\n        match self {\n            GroupsType::Slice { groups, .. } => groups,\n            GroupsType::Idx(_) => panic!(\"groups are index not slices\"),\n        }\n    }\n\n    pub fn get(&self, index: usize) -> GroupsIndicator<'_> {\n        match self {\n            GroupsType::Idx(groups) => {","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/pola-rs/polars/blob/68506541d2de983056c9eb244e1ea05fab377dfc/crates/polars-core/src/frame/group_by/position.rs#L483-L519","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Match on the enum instead of unwrapping: if let GroupsType::Idx(idx) = groups { ... } else { ... }","Use the Option-returning accessor groups.idx() to detect the representation before unwrapping","Convert representation explicitly (GroupsType::into_idx / sort_unsliced variants) before index-only code"],"exampleFix":"// before\nlet idx = groups.unwrap_idx();\n\n// after\nmatch groups.idx() {\n    Some(idx) => { /* index path */ },\n    None => { /* handle GroupsType::Slice */ },\n}","handlingStrategy":"type-guard","validationCode":"let is_idx = matches!(groups, GroupsType::Idx(_));\nif !is_idx { /* convert or take slice path */ }","typeGuard":"fn has_idx_groups(g: &GroupsType) -> bool {\n    matches!(g, GroupsType::Idx(_))\n}","tryCatchPattern":null,"preventionTips":["Treat GroupsType as a two-variant enum; never unwrap without matching","Use the Option accessors idx()/slice() instead of unwrap_idx()/unwrap_slice()","Test group-handling code with both sorted and unsorted keys to cover both representations"],"tags":["rust","polars","group-by","internal-api","panic","enum-variant"],"backgroundTag":"wrong-enum-variant-unwrapped","analyzedSha":"68506541d2de983056c9eb244e1ea05fab377dfc","analyzedAt":"2026-08-19T12:15:06.350Z","contentChangedAt":"2026-08-19T12:15:06.350Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}