{"record":{"id":"260653e144c14300","repo":"pola-rs/polars","slug":"length-to-be-non-zero","errorCode":null,"errorMessage":"Length to be non-zero","messagePattern":"Length to be non-zero","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/polars-arrow/src/offset.rs","lineNumber":315,"sourceCode":"        });\n        self.0.extend(offsets);\n        Ok(())\n    }\n\n    /// Extends itself from another [`Offsets`] sliced by `start, length`\n    /// # Errors\n    /// This function errors iff this operation overflows for the maximum value of `O`.\n    pub fn try_extend_from_slice(\n        &mut self,\n        other: &OffsetsBuffer<O>,\n        start: usize,\n        length: usize,\n    ) -> PolarsResult<()> {\n        if length == 0 {\n            return Ok(());\n        }\n        let other = &other.0[start..start + length + 1];\n        let other_length = other.last().expect(\"Length to be non-zero\");\n        let mut length = *self.last();\n        // check if the operation would overflow\n        length\n            .checked_add(other_length)\n            .ok_or_else(|| polars_err!(ComputeError: \"overflow\"))?;\n\n        let lengths = other.windows(2).map(|w| w[1] - w[0]);\n        let offsets = lengths.map(|new_length| {\n            length += new_length;\n            length\n        });\n        self.0.extend(offsets);\n        Ok(())\n    }\n\n    /// Returns the inner [`Vec`].\n    #[inline]\n    pub fn into_inner(self) -> Vec<O> {","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/pola-rs/polars/blob/fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e/crates/polars-arrow/src/offset.rs#L297-L333","documentation":"This panic comes from `OffsetsBuffer::try_extend_from_slice` in polars-arrow, which slices `other.0[start..start + length + 1]` and calls `.last().expect(\"Length to be non-zero\")` on the result. It means the sliced region of the offsets buffer was empty, so the code could not read the final offset needed to compute the appended length. The library treats a non-empty sliced offsets region as an internal invariant and panics rather than returning a `PolarsResult` error.","triggerScenarios":"Calling `Offsets::try_extend_from_slice(buffer, start, length)` with arguments such that `&other.0[start..start+length+1]` is an empty slice — i.e., a corrupt/truncated offsets buffer, or `start`/`length` values that do not match the actual contents of the offsets buffer. Note that `length == 0` short-circuits earlier, so only `length >= 1` with an empty or out-of-bounds-mapped slice region reaches the expect.","commonSituations":"Building list/binary view arrays by slicing another array's offsets with hand-computed start/length pairs; deserializing Arrow IPC or Parquet data whose offsets buffer was truncated or mis-declared; version mismatches where offset buffers were constructed by code with different invariants.","solutions":["Validate that `other.0.len() >= start + length + 1` and that the sliced region is non-empty before calling try_extend_from_slice.","Check that the source offsets buffer was produced by a trusted/validated constructor (e.g. OffsetsBuffer::try_from) rather than raw memory reinterpretation.","Downgrade to a guarded path: if the slice would be empty, return early instead of extending.","Verify array/IPC/Parquet producer and consumer versions match so offset buffers have the expected layout."],"exampleFix":"// before\nlet other = &other.0[start..start + length + 1];\nlet other_length = other.last().expect(\"Length to be non-zero\");\n// after\nlet other = other.0.get(start..start + length + 1)\n    .ok_or_else(|| polars_err!(ComputeError: \"offsets slice out of bounds\"))?;\nlet other_length = other.last()\n    .ok_or_else(|| polars_err!(ComputeError: \"empty offsets slice\"))?;","handlingStrategy":"validation","validationCode":"fn can_extend(offsets: &[i64], start: usize, length: usize) -> bool {\n    length > 0\n        && start.checked_add(length).map(|e| e + 1).map_or(false, |end| end <= offsets.len())\n        && !offsets.is_empty()\n}","typeGuard":"fn has_final_offset(slice: &[i64]) -> bool { !slice.is_empty() }","tryCatchPattern":null,"preventionTips":["Always construct OffsetsBuffer via try_from/new so offsets are validated (monotonic, non-empty).","Never hand-compute start/length pairs against raw offset slices without bounds checks.","Add debug_assert!s for `start + length + 1 <= offsets.len()` in kernel code.","Keep Arrow producer/consumer versions aligned (IPC/Parquet)."],"tags":["arrow","offsets","panic","slice-bounds","rust"],"backgroundTag":"index-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"}