{"record":{"id":"2c114ba18128b8a4","repo":"clockworklabs/SpacetimeDB","slug":"log-format-version-mismatch-current-segmen","errorCode":null,"errorMessage":"{}: log format version mismatch: current={} segment={}","messagePattern":"(.+?): log format version mismatch: current=(.+?) segment=(.+?)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/commitlog/src/repo/mod.rs","lineNumber":380,"sourceCode":"            return Ok(ResumedSegment::Corrupted(sofar));\n        }\n        Err(error::SegmentMetadata::Io(e)) => {\n            return Err(with_segment_context(\"extracting segment metadata\", repo, offset, e));\n        }\n        Ok(meta) => meta,\n    };\n    meta.header\n        .ensure_compatible(opts.log_format_version, Commit::CHECKSUM_ALGORITHM)\n        .map_err(|msg| {\n            with_segment_context(\n                \"checking segment compatibility\",\n                repo,\n                offset,\n                io::Error::new(io::ErrorKind::InvalidData, msg),\n            )\n        })?;\n    if meta.header.log_format_version != opts.log_format_version {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\n                \"{}: log format version mismatch: current={} segment={}\",\n                segment_label(repo, offset),\n                opts.log_format_version,\n                meta.header.log_format_version\n            ),\n        ));\n    }\n    guard_non_empty(&meta)?;\n\n    if reader.sealed() {\n        Ok(ResumedSegment::Sealed(meta))\n    } else {\n        let mut writer = repo.open_segment_writer(offset)?;\n        // Ensure that the segment's size is exactly what we determined.\n        //\n        // When `Metadata` encounters EOF, it could be that there actually are","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/3653d2ed498fddbd83b7062aa6bf8970e18635ec/crates/commitlog/src/repo/mod.rs#L362-L398","documentation":"On resume, each segment header first passes Header::ensure_compatible (supported version and checksum algorithm), then must match Options::log_format_version exactly. A supported-but-different version yields io::ErrorKind::InvalidData with current vs segment values. This is a hard compatibility gate: the library will not open logs written in a different format version.","triggerScenarios":"Setting Options::log_format_version to a value different from the one the on-disk segments were written with; upgrading the crate when DEFAULT_LOG_FORMAT_VERSION changed, then reopening the old data directory; downgrading a binary below the version that wrote the segments.","commonSituations":"Release upgrades/downgrades; explicitly overriding log_format_version in Options (e.g. to try a new format) against existing data; mixed-version nodes in a cluster sharing one storage directory.","solutions":["Do not override log_format_version; keep the default that matches the on-disk data","Inspect a segment header (byte 6 after the '(ds)^2' magic) to learn the on-disk version, then configure Options to match","Migrate data: rewrite segments into the new format with a converter before switching versions","Start a fresh commitlog directory for the new format after archiving the old one"],"exampleFix":"// before\nlet mut opts = Options::default();\nopts.log_format_version = 2; // segments on disk were written as 1\n\n// after\n// keep the version that matches the on-disk segments\nlet opts = Options::default();","handlingStrategy":"validation","validationCode":"// Read the on-disk version byte (offset 6, after the 6-byte magic) before opening\nfn on_disk_version(path: &std::path::Path) -> io::Result<u8> {\n    use std::io::Read as _;\n    let mut f = std::fs::File::open(path)?;\n    let mut buf = [0u8; segment::Header::LEN];\n    f.read_exact(&mut buf)?;\n    assert_eq!(&buf[..6], b\"(ds)^2\", \"not a commitlog segment\");\n    Ok(buf[6])\n}","typeGuard":"fn is_version_mismatch(err: &io::Error) -> bool {\n    err.kind() == io::ErrorKind::InvalidData && err.to_string().contains(\"log format version mismatch\")\n}","tryCatchPattern":"match open_commitlog(&dir, &opts) {\n    Ok(log) => Ok(log),\n    Err(e) if is_version_mismatch(&e) => Err(friendly(e)), // surface 'pin Options::log_format_version to the segment version'\n    Err(e) => Err(e),\n}","preventionTips":["Never override Options::log_format_version unless migrating on-disk data in the same change","Record the format version in your deployment config so upgrades can pre-check compatibility","Pin the crate version in CI for nodes sharing a storage directory"],"tags":["rust","commitlog","version-mismatch","invalid-data","upgrade"],"backgroundTag":"file-format-version-mismatch","analyzedSha":"3653d2ed498fddbd83b7062aa6bf8970e18635ec","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}