clockworklabs/SpacetimeDB · error · io::Error
segment {offset} does not exist
Error message
segment {offset} does not exist What it means
The in-memory commitlog Repo's open_segment_writer (and open_segment_reader, which delegates to it) looks up the requested u64 offset in its BTreeMap of segments. If no segment was ever created (or it was removed) at that offset, it returns io::ErrorKind::NotFound with 'segment {offset} does not exist'. Readers and writers can only be opened for segments that a prior create_segment call established.
Source
Thrown at crates/dst/src/sim/commitlog.rs:197
}
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_reader(&self, offset: u64) -> io::Result<Self::SegmentReader> {
self.open_segment_writer(offset).map(Into::into)
}
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 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"),
));
}
Ok(())
}View on GitHub (pinned to 6dee26c6ef)
Solutions
- Ensure create_segment(offset, header) has completed successfully before opening readers/writers for that offset
- If the segment may legitimately be absent, treat NotFound as end-of-log instead of an error
- Verify the offset arithmetic against the segment rotation size used when segments were created
- If the segment was removed by remove_segment, recreate it with create_segment before opening
Example fix
// before
let reader = repo.open_segment_reader(offset)?; // NotFound on fresh repo
// after
let reader = match repo.open_segment_reader(offset) {
Ok(r) => r,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(None), // end of log
Err(e) => return Err(e),
}; Defensive patterns
Strategy: try-catch
Validate before calling
// Derive the set of offsets you expect, from creation bookkeeping:
let expected: BTreeSet<u64> = created_offsets.iter().copied().collect();
if !expected.contains(&offset) {
return Ok(None); // no such segment: treat as end-of-log
} Try / catch
let reader = match repo.open_segment_reader(offset) {
Ok(r) => r,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
return Ok(None); // graceful end-of-log
}
Err(e) => return Err(e.into()),
}; Prevention
- Always create_segment before opening readers/writers for an offset in replay code
- Treat NotFound from open as end-of-log rather than fatal in log-scan loops
- Compute segment offsets from the same segment-size constant used at creation
- Seed test repos deterministically so expected offsets are known
When it happens
Trigger: Calling open_segment_reader/open_segment_writer for an offset before create_segment ran; opening a segment after remove_segment removed it; computing the next segment offset as last_offset + segment_size when the log actually ended at a different boundary; replaying against a fresh/empty Memory repo.
Common situations: Recovery code that assumes a segment exists because it was recorded elsewhere; unit tests forgetting to seed the repo; truncation/rotation logic removing a segment and then a straggler reader trying to open it.
Related errors
- segment {offset} already exists
- write position overflow
- invalid seek to a negative or overflowing position
- allocation size overflow
- no space left on device
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/601a2534007f85c0.
Report an issue: GitHub.