{"record":{"id":"8c59aad4ed182e26","repo":"pola-rs/polars","slug":"slice-index-starts-at-start-but-ends-at-end","errorCode":null,"errorMessage":"slice index starts at {start} but ends at {end}","messagePattern":"slice index starts at (.+?) but ends at (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/polars-utils/src/range.rs","lineNumber":14,"sourceCode":"use std::ops;\n\n// Copied from the stdlib.\nfn slice_index_fail(start: usize, end: usize, len: usize) -> ! {\n    if start > len {\n        panic!(\"range start index {start} out of range for slice of length {len}\",)\n    }\n\n    if end > len {\n        panic!(\"range end index {end} out of range for slice of length {len}\",)\n    }\n\n    if start > end {\n        panic!(\"slice index starts at {start} but ends at {end}\",)\n    }\n\n    // Only reachable if the range was a `RangeInclusive` or a\n    // `RangeToInclusive`, with `end == len`.\n    panic!(\"range end index {end} out of range for slice of length {len}\",)\n}\n\n#[must_use]\npub fn check_range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>\nwhere\n    R: ops::RangeBounds<usize>,\n{\n    let len = bounds.end;\n    let end = match range.end_bound() {\n        ops::Bound::Included(&end) if end >= len => slice_index_fail(0, end, len),\n        // Cannot overflow because `end < len` implies `end < usize::MAX`.\n        ops::Bound::Included(&end) => end + 1,\n","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/pola-rs/polars/blob/fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e/crates/polars-utils/src/range.rs#L1-L32","documentation":"slice_index_fail panics with 'slice index starts at {start} but ends at {end}' when start > end, i.e. an inverted range. This matches stdlib behavior and is reached through check_range when callers pass a range whose bounds are reversed.","triggerScenarios":"Passing a range like 10..5 or an inclusive range where the inclusive start exceeds the inclusive end to any API that slices via check_range.","commonSituations":"Variables accidentally swapped at the call site; ranges built from descending sorts; computing [last..first] instead of [first..last] after reordering.","solutions":["Swap the bounds if inverted: (min(start,end), max(start,end))","Validate start <= end before slicing and return an empty result if not","Normalize ranges with RangeBounds helpers before calling the slicing API","Check for variable-order bugs at the call site that built the range"],"exampleFix":"// before\nlet out = check_range(start..end, ..len);\n// after\nlet (start, end) = if start > end { (end, start) } else { (start, end) };\nlet out = check_range(start..end, ..len);","handlingStrategy":"validation","validationCode":"def ordered_range(start, end):\n    if start > end:\n        start, end = end, start\n    return start, end","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Construct ranges from (low, high) with an explicit order-normalizing helper","Watch for swapped arguments in range-producing functions","Add unit tests for inverted-range inputs","Prefer named parameters (start=, end=) at call sites"],"tags":["rust","panic","slicing","range"],"backgroundTag":"argument-out-of-range","analyzedSha":"fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e","analyzedAt":"2026-09-18T22:14:11.667Z","contentChangedAt":"2026-09-18T22:14:11.667Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}