clockworklabs/SpacetimeDB · error · io::Error
InvalidInput
InvalidInput
Error message
invalid seek to a negative or overflowing position
What it means
A Seek on an in-memory segment computed a target position that is negative (before byte 0) or overflows u64, so checked_add_signed failed (InvalidInput). This mirrors std's seek semantics: SeekFrom::Start(n) never fails here; only End/Current arithmetic can. The segment's own state is unchanged.
Source
Thrown at crates/commitlog/src/repo/mem/segment.rs:167
}
}
impl io::Seek for Segment {
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
let (base_pos, offset) = match pos {
io::SeekFrom::Start(n) => {
self.pos = n;
return Ok(n);
}
io::SeekFrom::End(n) => (self.len() as u64, n),
io::SeekFrom::Current(n) => (self.pos, n),
};
match base_pos.checked_add_signed(offset) {
Some(n) => {
self.pos = n;
Ok(n)
}
None => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid seek to a negative or overflowing position",
)),
}
}
}
impl SegmentLen for Segment {
fn segment_len(&mut self) -> io::Result<u64> {
Ok(self.len() as _)
}
}
impl FileLike for Segment {
fn fsync(&mut self) -> io::Result<()> {
Ok(())
}
View on GitHub (pinned to 524b4487d9)
Solutions
- Compute the absolute target with checked/saturating u64 arithmetic first, then seek with SeekFrom::Start
- Clamp rewind amounts: target = len.saturating_sub(rewind)
- Validate externally sourced offsets against the segment length before seeking
Example fix
// before reader.seek(io::SeekFrom::End(-(skip as i64)))?; // fails when skip > len // after let len = reader.seek(io::SeekFrom::End(0))?; let target = len.saturating_sub(skip); reader.seek(io::SeekFrom::Start(target))?;
Defensive patterns
Strategy: validation
Validate before calling
// compute absolute targets instead of relative seeks
fn rewind_to(reader: &mut impl io::Seek, skip: u64) -> io::Result<u64> {
let len = reader.seek(io::SeekFrom::End(0))?;
let target = len.saturating_sub(skip); // clamp at 0
reader.seek(io::SeekFrom::Start(target))
} Type guard
fn is_invalid_seek(e: &io::Error) -> bool {
e.kind() == io::ErrorKind::InvalidInput
&& e.to_string().contains("invalid seek to a negative or overflowing position")
} Prevention
- Prefer SeekFrom::Start with a pre-computed u64 over End/Current with i64 deltas
- Use checked_add/checked_sub/saturating arithmetic on offsets sourced from external input
When it happens
Trigger: seek(SeekFrom::End(-n)) with n greater than the segment length; seek(SeekFrom::Current(negative)) that would move before position 0; relative skips computed from untrusted or underflowing i64 offsets.
Common situations: Replay/scan code that rewinds by a delta larger than the file; converting external i64 offsets into seeks without clamping.
Related errors
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/fb08f379a8f355d0.
Report an issue: GitHub.