{"record":{"id":"1d8e49bb8d23d59f","repo":"clockworklabs/SpacetimeDB","slug":"segment-header-does-not-start-with-magic-expected","errorCode":null,"errorMessage":"segment header does not start with magic: expected {:02x?}, got {:02x?}","messagePattern":"segment header does not start with magic: expected (.+?), got (.+?)","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/commitlog/src/segment.rs","lineNumber":57,"sourceCode":"\n    pub fn write<W: io::Write>(&self, mut out: W) -> io::Result<()> {\n        out.write_all(&MAGIC)?;\n        out.write_all(&[self.log_format_version, self.checksum_algorithm, 0, 0])?;\n\n        Ok(())\n    }\n\n    pub fn decode<R: io::Read>(mut read: R) -> io::Result<Self> {\n        let mut buf = [0; Self::LEN];\n        read.read_exact(&mut buf).map_err(|e| {\n            io::Error::new(\n                e.kind(),\n                format!(\"failed to read segment header ({} bytes): {}\", Self::LEN, e),\n            )\n        })?;\n\n        if !buf.starts_with(&MAGIC) {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"segment header does not start with magic: expected {:02x?}, got {:02x?}\",\n                    MAGIC,\n                    &buf[..MAGIC.len()]\n                ),\n            ));\n        }\n\n        Ok(Self {\n            log_format_version: buf[MAGIC.len()],\n            checksum_algorithm: buf[MAGIC.len() + 1],\n        })\n    }\n\n    pub fn ensure_compatible(&self, max_log_format_version: u8, checksum_algorithm: u8) -> Result<(), String> {\n        if self.log_format_version > max_log_format_version {\n            return Err(format!(\"unsupported log format version: {}\", self.log_format_version));","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/3653d2ed498fddbd83b7062aa6bf8970e18635ec/crates/commitlog/src/segment.rs#L39-L75","documentation":"After successfully reading 10 bytes, Header::decode requires the first 6 bytes to equal the MAGIC constant b\"(ds)^2\". A different prefix returns io::ErrorKind::InvalidData with expected/got hex dumps. The file exists and is long enough, but it is not a commitlog segment.","triggerScenarios":"Pointing the repo at a directory containing unrelated files that get picked up as segments; a segment file overwritten or corrupted so the header is gone; reading a file produced by a different product or an incompatible fork.","commonSituations":"Misconfigured repo path (e.g. data dir shared with other storage); stray files dropped into the log directory; corruption at offset 0; restoring wrong files from backup.","solutions":["Inspect the first bytes (xxd file | head -1) and compare with 28 64 73 29 5e 32 ('(ds)^2')","Point the repo at the correct data directory containing only commitlog segments","Quarantine or delete the stray file after confirming it is not a misnamed segment","Restore the segment from a replica or backup if it is genuinely corrupted"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const MAGIC: &[u8; 6] = b\"(ds)^2\";\nfn is_segment_file(path: &std::path::Path) -> io::Result<bool> {\n    use std::io::Read as _;\n    let mut f = std::fs::File::open(path)?;\n    let mut magic = [0u8; 6];\n    match f.read_exact(&mut magic) {\n        Ok(()) => Ok(&magic == MAGIC),\n        Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => Ok(false),\n        Err(e) => Err(e),\n    }\n}","typeGuard":"fn is_bad_magic(err: &io::Error) -> bool {\n    err.kind() == io::ErrorKind::InvalidData && err.to_string().contains(\"does not start with magic\")\n}","tryCatchPattern":"match segment::Header::decode(&mut file) {\n    Ok(h) => Ok(h),\n    Err(e) if is_bad_magic(&e) => {\n        // do not delete blindly: quarantine and alert; likely wrong directory\n        quarantine(&path)?;\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Dedicate the repo directory to commitlog segments only","Validate the magic of the newest segment at startup before resuming","Hexdump unfamiliar files before deciding they are corrupt"],"tags":["rust","commitlog","magic-number","invalid-data","corruption"],"backgroundTag":"invalid-magic-number","analyzedSha":"3653d2ed498fddbd83b7062aa6bf8970e18635ec","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}