pola-rs/polars · error · std::io::Error

invalid seek to a negative or overflowing position

Error message

invalid seek to a negative or overflowing position

What it means

ChunkedBytesCursor::seek returns an io::Error of kind InvalidInput when the requested seek position (base position plus signed offset) is negative or overflows usize. The cursor cannot represent such a position, so the seek fails instead of wrapping. It surfaces as a standard std::io::Error, typically wrapped in a Polars error by higher layers.

Solutions

  1. Verify the file is not truncated or corrupted; re-download/regenerate the source file
  2. Check computed offsets before seeking (use checked arithmetic on offsets)
  3. Ensure SeekFrom::Start values fit within u64/usize bounds and Current/End offsets don't go negative

Example fix

// before
let off = row_group_offset - computed_offset; // may underflow
cursor.seek(SeekFrom::Current(off))?;
// after
let off = row_group_offset.checked_sub(computed_offset).ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "negative offset"))?;
cursor.seek(SeekFrom::Current(off))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: bounds-check before seeking
fn safe_seek(cursor: &mut ChunkedBytesCursor, pos: u64) -> std::io::Result<()> {
    if pos > usize::MAX as u64 { return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "position out of range")); }
    cursor.seek(std::io::SeekFrom::Start(pos))
}

Type guard

fn seekable(pos: u64) -> bool { pos <= usize::MAX as u64 }

Try / catch

match cursor.seek(SeekFrom::Current(off)) {
    Ok(p) => { /* use p */ },
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => { /* negative/overflowing seek: recover or abort */ },
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling Seek::seek with SeekFrom::Start larger than usize::MAX, a SeekFrom::Current/End offset that moves before position 0, or a target beyond usize addressable range on a ChunkedBytesCursor.

Common situations: Corrupted Parquet/IPC metadata containing out-of-range offsets; code computing byte offsets with underflow; reading truncated files where stored offsets exceed actual buffer length combined with End-relative seeks.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at crates/polars-utils/src/chunked_bytes_cursor.rs:129

impl<'a, T> std::io::Seek for FixedSizeChunkedBytesCursor<'a, T> {
    fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
        // Mostly copied from io::Cursor::seek().
        use std::io::SeekFrom;

        let (base_pos, offset) = match pos {
            SeekFrom::Start(n) => {
                self.position = usize::try_from(n).unwrap().min(self.total_size);
                return Ok(self.position as u64);
            },
            SeekFrom::End(n) => (self.total_size as u64, n),
            SeekFrom::Current(n) => (self.position as u64, n),
        };
        match base_pos.checked_add_signed(offset) {
            Some(n) => {
                self.position = usize::try_from(n).unwrap();
                Ok(self.position as u64)
            },
            None => Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                "invalid seek to a negative or overflowing position",
            )),
        }
    }
}

View on GitHub (pinned to fe841f959e)