pola-rs/polars · error

offset exceeds usize limits

Error message

offset exceeds usize limits

What it means

Column::split_at converts its i64 offset into a usize to resize a scalar column (negative offsets are made absolute first). If the offset's magnitude does not fit in usize, usize::try_from fails and the expect panics with 'offset exceeds usize limits'. In practice this is reachable on 32-bit targets with offsets above u32::MAX, or with degenerate values such as i64::MIN.

Source

Thrown at crates/polars-core/src/frame/column/mod.rs:637

        self.slice(-(len as i64), len)
    }
    pub fn slice(&self, offset: i64, length: usize) -> Column {
        match self {
            Column::Series(s) => s.slice(offset, length).into(),
            Column::Scalar(s) => {
                let (_, length) = slice_offsets(offset, length, s.len());
                s.resize(length).into()
            },
        }
    }

    pub fn split_at(&self, offset: i64) -> (Column, Column) {
        match self {
            Column::Scalar(c) => {
                let len = c.len();
                let offset = if offset < 0 {
                    let offset_abs = usize::try_from(offset.strict_abs())
                        .expect("offset exceeds usize limits")
                        .min(len);
                    len - offset_abs
                } else {
                    usize::try_from(offset)
                        .expect("offset exceeds usize limits")
                        .min(len)
                };
                (
                    Column::Scalar(c.resize(offset)),
                    Column::Scalar(c.resize(len - offset)),
                )
            },
            Column::Series(_) => {
                let (l, r) = self.as_materialized_series().split_at(offset);
                (l.into(), r.into())
            },
        }
    }

View on GitHub (pinned to 68506541d2)

Solutions

  1. Clamp the offset to 0..=len before calling split_at: offset = offset.clamp(0, len as i64)
  2. Fix the arithmetic that produced the out-of-range offset (check for i64::MIN/i64::MAX sentinels or overflow)
  3. Build for a 64-bit target so usize covers the whole positive i64 range

Example fix

// before
let (l, r) = col.split_at(offset); // offset may be i64::MIN

// after
let offset = offset.clamp(0, col.len() as i64);
let (l, r) = col.split_at(offset);
Defensive patterns

Strategy: validation

Validate before calling

fn safe_offset(offset: i64, len: usize) -> usize {
    let len = len as i64;
    offset.clamp(0, len) as usize
}

Prevention

When it happens

Trigger: Calling Column::split_at / Series::split_at / DataFrame::split_at on a scalar column with an offset outside usize's range: e.g. i64::MAX or i64::MIN offsets on 32-bit builds, or offsets produced by overflowing arithmetic (e.g. -1 * huge_value).

Common situations: Running polars on 32-bit targets (wasm32, armv7) and passing offsets computed from user input or subtraction that underflowed/overflowed; offsets coming from a length that was itself an i64 converted without clamping.

Related errors


AI-assisted analysis of pola-rs/polars@68506541d2 (2026-08-19). Data as JSON: /api/errors/7fcba5e7f059b2fc. Report an issue: GitHub.