pola-rs/polars · error

cannot use offsetted() on a negative slice

Error message

cannot use offsetted() on a negative slice

What it means

Slice::offsetted only works on Slice::Positive; applying an offset from a negative slice panics because the absolute start position of a from-the-end slice is undefined until it is materialized against an actual length.

Solutions

  1. Ensure the slice is Slice::Positive before calling offsetted(); convert negative slices first
  2. Match on the enum and implement negative handling at the call site
  3. Track slice provenance so negative slices are resolved once, early, against a known length

Example fix

// before
let shifted = slice.offsetted(pos);
// after
let shifted = match slice {
    s @ Slice::Positive { .. } => s.offsetted(pos),
    Slice::Negative { .. } => resolve_to_positive(slice, total_len).offsetted(pos),
};
Defensive patterns

Strategy: type-guard

Type guard

fn offset_slice(s: Slice, pos: usize, total_len: usize) -> Slice {
    match s { Slice::Positive { .. } => s.offsetted(pos), Slice::Negative { .. } => resolve(s, total_len).offsetted(pos) }
}

Prevention

When it happens

Trigger: Calling offsetted() on a Slice::Negative, e.g. when chaining window/slice operations where an earlier slice was negative.

Common situations: Composition of slice operations (offset then slice again) where one input slice came from negative indexing; refactors that removed an earlier variant check.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/337ef0cf0e69ed83. Report an issue: GitHub.

Appendix: source

Thrown at crates/polars-utils/src/slice_enum.rs:66

    /// Returns the end position of the slice (offset + len).
    ///
    /// # Panics
    /// Panics if self is negative.
    pub fn end_position(&self) -> usize {
        let Slice::Positive { offset, len } = self.clone() else {
            panic!("cannot use end_position() on a negative slice");
        };

        offset.saturating_add(len)
    }

    /// Returns the equivalent slice to apply from an offsetted position.
    ///
    /// # Panics
    /// Panics if self is negative.
    pub fn offsetted(self, position: usize) -> Self {
        let Slice::Positive { offset, len } = self else {
            panic!("cannot use offsetted() on a negative slice");
        };

        let (offset, len) = if position <= offset {
            (offset - position, len)
        } else {
            let n_past_offset = position - offset;
            (0, len.saturating_sub(n_past_offset))
        };

        Slice::Positive { offset, len }
    }

    /// Restricts the bounds of the slice to within a number of rows. Negative slices will also
    /// be translated to the positive equivalent.
    pub fn restrict_to_bounds(self, n_rows: usize) -> Self {
        match self {
            Slice::Positive { offset, len } => {
                let offset = offset.min(n_rows);

View on GitHub (pinned to fe841f959e)