clockworklabs/SpacetimeDB · error · std::io::Error
segment {offset} does not exist
Error message
segment {offset} does not exist What it means
In-memory Memory::open_segment_writer (and, by delegation, open_segment_reader) failed because no segment exists in the map at the given offset; the BTreeMap lookup miss is converted to io::ErrorKind::NotFound with this message. It signals offset bookkeeping pointing at a segment that was never created or has been removed - on the filesystem repo the OS returns the equivalent NotFound from opening a nonexistent file.
Source
Thrown at crates/commitlog/src/repo/mem.rs:85
io::ErrorKind::AlreadyExists,
format!("segment {offset} already exists"),
));
}
}
btree_map::Entry::Vacant(entry) => {
let storage = entry.insert(Arc::new(RwLock::new(Storage::new())));
Segment::from_shared(self.space.clone(), storage.clone())
}
};
header.write(&mut segment)?;
Ok(segment)
}
fn open_segment_writer(&self, offset: u64) -> io::Result<Self::SegmentWriter> {
let inner = self.segments.read().unwrap();
let Some(buf) = inner.get(&offset) else {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("segment {offset} does not exist"),
));
};
Ok(Segment::from_shared(self.space.clone(), buf.clone()))
}
fn open_segment_reader(&self, offset: u64) -> io::Result<Self::SegmentReader> {
self.open_segment_writer(offset).map(Into::into)
}
fn remove_segment(&self, offset: u64) -> io::Result<()> {
let mut inner = self.segments.write().unwrap();
if inner.remove(&offset).is_none() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("segment {offset} does not exist"),
));View on GitHub (pinned to 6dee26c6ef)
Solutions
- Create the segment before opening it - track the set of live offsets in the harness.
- Re-check offset arithmetic: after N commits the next segment offset is head.min_tx_offset + head commit count, not a file index.
- If the segment was removed deliberately, stop referencing that offset.
Example fix
// before let seg = repo.open_segment_writer(next_offset)?; // NotFound: never created // after let seg = repo.create_segment(next_offset, header)?; let seg = repo.open_segment_writer(next_offset)?; // open only after create
Defensive patterns
Strategy: try-catch
Try / catch
match repo.open_segment_writer(off) {
Ok(seg) => seg,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => repo.create_segment(off, hdr)?,
Err(e) => return Err(e.into()),
} Prevention
- Maintain an explicit list of live segment offsets in test harnesses instead of assuming existence.
- Follow create-then-open: never open an offset you did not create or verify.
- After remove_segment, purge the offset from any cached bookkeeping.
When it happens
Trigger: Opening a segment offset that was never created (or was removed) on a Memory repo: opening the head before the first create_segment, computing an offset from the wrong base, or reopening a segment after remove_segment.
Common situations: Test harnesses that assume a segment exists after truncation/removal; offset math that forgets a head segment starts at its min_tx_offset rather than zero after rollover.
Related errors
- segment {offset} already exists
- refusing to compress mutable segment {head_offset}
- invalid seek to a negative or overflowing position
- no space left on device
- repo {}: too many empty segments: {}
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/08744408edc8efa1.
Report an issue: GitHub.