{"record":{"id":"4d329820976443cd","repo":"pola-rs/polars","slug":"groups-are-index-not-slices","errorCode":null,"errorMessage":"groups are index not slices","messagePattern":"groups are index not slices","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/polars-core/src/frame/group_by/position.rs","lineNumber":513,"sourceCode":"    /// # 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) => {\n                let first = groups.first[index];\n                let all = &groups.all[index];\n                GroupsIndicator::Idx((first, all))\n            },\n            GroupsType::Slice { groups, .. } => GroupsIndicator::Slice(groups[index]),\n        }\n    }\n\n    /// Get a mutable reference to the `GroupsIdx`.\n    ///\n    /// # Panic\n    ///","sourceCodeStart":495,"sourceCodeEnd":531,"githubUrl":"https://github.com/pola-rs/polars/blob/68506541d2de983056c9eb244e1ea05fab377dfc/crates/polars-core/src/frame/group_by/position.rs#L495-L531","documentation":"The mirror of unwrap_idx: unwrap_slice() returns the GroupsSlice (offset/length pairs) and panics with 'groups are index not slices' when groups are stored as GroupsType::Idx (first/all index vectors, the representation used for unsorted/hashed grouping).","triggerScenarios":"Calling GroupsType::unwrap_slice() on groups from a hashed group_by over unsorted keys, or any code path that assumes the sliced representation but receives index-based groups.","commonSituations":"Code paths tuned for the fast slice representation that receive groups from a generic group_by; polars-internal or plugin code that hard-codes one representation after a schema/plan change alters which grouping strategy runs.","solutions":["Match on GroupsType and handle both variants","Check groups.slice() (Option accessor) before calling unwrap_slice","Force the needed representation with the provided conversion helpers before use"],"exampleFix":"// before\nlet slices = groups.unwrap_slice();\n\n// after\nmatch groups.slice() {\n    Some(s) => { /* slice path */ },\n    None => { /* GroupsType::Idx path */ },\n}","handlingStrategy":"type-guard","validationCode":"let is_slice = matches!(groups, GroupsType::Slice { .. });\nif !is_slice { /* take idx path or convert */ }","typeGuard":"fn has_slice_groups(g: &GroupsType) -> bool {\n    matches!(g, GroupsType::Slice { .. })\n}","tryCatchPattern":null,"preventionTips":["Prefer iteration via groups.get()/par_iter() which abstract over the representation","Gate unwrap_slice() behind a representation check","Keep group-manipulation code representation-agnostic where possible"],"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"}