{"record":{"id":"601a2534007f85c0","repo":"clockworklabs/SpacetimeDB","slug":"segment-offset-does-not-exist-601a25","errorCode":null,"errorMessage":"segment {offset} does not exist","messagePattern":"segment (.+?) does not exist","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/dst/src/sim/commitlog.rs","lineNumber":197,"sourceCode":"            }\n            btree_map::Entry::Vacant(entry) => {\n                let storage = entry.insert(Arc::new(RwLock::new(Storage::new())));\n                Segment::from_shared(self.space.clone(), storage.clone())\n            }\n        };\n        header.write(&mut segment)?;\n\n        Ok(segment)\n    }\n\n    fn open_segment_reader(&self, offset: u64) -> io::Result<Self::SegmentReader> {\n        self.open_segment_writer(offset).map(Into::into)\n    }\n\n    fn open_segment_writer(&self, offset: u64) -> io::Result<Self::SegmentWriter> {\n        let inner = self.segments.read().unwrap();\n        let Some(buf) = inner.get(&offset) else {\n            return Err(io::Error::new(\n                io::ErrorKind::NotFound,\n                format!(\"segment {offset} does not exist\"),\n            ));\n        };\n        Ok(Segment::from_shared(self.space.clone(), buf.clone()))\n    }\n\n    fn remove_segment(&self, offset: u64) -> io::Result<()> {\n        let mut inner = self.segments.write().unwrap();\n        if inner.remove(&offset).is_none() {\n            return Err(io::Error::new(\n                io::ErrorKind::NotFound,\n                format!(\"segment {offset} does not exist\"),\n            ));\n        }\n\n        Ok(())\n    }","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/dst/src/sim/commitlog.rs#L179-L215","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlet reader = repo.open_segment_reader(offset)?; // NotFound on fresh repo\n\n// after\nlet reader = match repo.open_segment_reader(offset) {\n    Ok(r) => r,\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(None), // end of log\n    Err(e) => return Err(e),\n};","handlingStrategy":"try-catch","validationCode":"// Derive the set of offsets you expect, from creation bookkeeping:\nlet expected: BTreeSet<u64> = created_offsets.iter().copied().collect();\nif !expected.contains(&offset) {\n    return Ok(None); // no such segment: treat as end-of-log\n}","typeGuard":null,"tryCatchPattern":"let reader = match repo.open_segment_reader(offset) {\n    Ok(r) => r,\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {\n        return Ok(None); // graceful end-of-log\n    }\n    Err(e) => return Err(e.into()),\n};","preventionTips":["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"],"tags":["commitlog","storage","rust","simulation","spacetimedb"],"backgroundTag":"segment-not-found","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}