{"record":{"id":"f125d4d9c5db1782","repo":"clockworklabs/SpacetimeDB","slug":"segment-offset-already-exists-f125d4","errorCode":null,"errorMessage":"segment {offset} already exists","messagePattern":"segment (.+?) already exists","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/dst/src/sim/commitlog.rs","lineNumber":174,"sourceCode":"impl fmt::Display for Memory {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(\"<dst-memory>\")\n    }\n}\n\nimpl Repo for Memory {\n    type SegmentWriter = Segment;\n    type SegmentReader = ReadOnlySegment;\n\n    fn create_segment(&self, offset: u64, header: Header) -> io::Result<Self::SegmentWriter> {\n        let mut inner = self.segments.write().unwrap();\n        let mut segment = match inner.entry(offset) {\n            btree_map::Entry::Occupied(entry) => {\n                let entry = entry.get();\n                if entry.read().unwrap().is_empty() {\n                    Segment::from_shared(self.space.clone(), entry.clone())\n                } else {\n                    return Err(io::Error::new(\n                        io::ErrorKind::AlreadyExists,\n                        format!(\"segment {offset} already exists\"),\n                    ));\n                }\n            }\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    }","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/dst/src/sim/commitlog.rs#L156-L192","documentation":"The in-memory commitlog Repo implementation (crates/dst/src/sim/commitlog.rs) stores segments in a BTreeMap keyed by u64 offset. create_segment returns AlreadyExists when a segment at that offset is already present AND non-empty. Re-creating a segment that exists but is still empty is deliberately allowed (treated as reclaiming crash-recovery scratch space) via Segment::from_shared on the existing storage.","triggerScenarios":"Calling Repo::create_segment(offset, header) twice for the same offset when the first segment has had bytes written or its header written; a log replay/recovery routine that unconditionally recreates segments it discovers; two writers racing to create the same offset in a test harness.","commonSituations":"Simulator/test harnesses that replay a commit log from scratch without clearing the Memory repo; retry logic that assumes create is idempotent; off-by-one segment-offset computation that collides with an existing segment.","solutions":["If the segment already exists and you want to reuse it, call open_segment_writer(offset) instead of create_segment","Call remove_segment(offset) first when you truly want to recreate it from scratch","Reset or recreate the Memory repo between replays/tests so state does not leak","Check your offset math — segments are keyed by exact u64 offset, so an off-by-one lands on a neighbor"],"exampleFix":"// before\nlet seg = repo.create_segment(offset, header)?; // AlreadyExists on replay\n\n// after\nlet seg = match repo.create_segment(offset, header.clone()) {\n    Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => repo.open_segment_writer(offset)?,\n    Ok(seg) => seg,\n    Err(e) => return Err(e),\n};","handlingStrategy":"try-catch","validationCode":"// Memory repo exposes no exists(); approximate by probing a reader:\nfn segment_exists(repo: &Memory, offset: u64) -> bool {\n    matches!(repo.open_segment_reader(offset), Ok(_))\n}","typeGuard":null,"tryCatchPattern":"let segment = match repo.create_segment(offset, header.clone()) {\n    Ok(seg) => seg,\n    Err(ref e) if e.kind() == std::io::ErrorKind::AlreadyExists => {\n        repo.open_segment_writer(offset)? // reuse existing segment\n    }\n    Err(e) => return Err(e.into()),\n};","preventionTips":["Prefer open_segment_writer when the segment may already exist; reserve create_segment for first creation","Make replay routines idempotent: create-or-open, never bare create","Reset the Memory repo between test replays so leftover state cannot collide","Unit-test the replay path twice in a row to catch non-idempotent creation"],"tags":["commitlog","storage","rust","simulation","spacetimedb"],"backgroundTag":"segment-already-exists","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}