clockworklabs/SpacetimeDB · error · std::io::Error

{}: log format version mismatch: current={} segment={}

Error message

{}: log format version mismatch: current={} segment={}

What it means

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.

Source

Thrown at crates/commitlog/src/repo/mod.rs:380

            return Ok(ResumedSegment::Corrupted(sofar));
        }
        Err(error::SegmentMetadata::Io(e)) => {
            return Err(with_segment_context("extracting segment metadata", repo, offset, e));
        }
        Ok(meta) => meta,
    };
    meta.header
        .ensure_compatible(opts.log_format_version, Commit::CHECKSUM_ALGORITHM)
        .map_err(|msg| {
            with_segment_context(
                "checking segment compatibility",
                repo,
                offset,
                io::Error::new(io::ErrorKind::InvalidData, msg),
            )
        })?;
    if meta.header.log_format_version != opts.log_format_version {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!(
                "{}: log format version mismatch: current={} segment={}",
                segment_label(repo, offset),
                opts.log_format_version,
                meta.header.log_format_version
            ),
        ));
    }
    guard_non_empty(&meta)?;

    if reader.sealed() {
        Ok(ResumedSegment::Sealed(meta))
    } else {
        let mut writer = repo.open_segment_writer(offset)?;
        // Ensure that the segment's size is exactly what we determined.
        //
        // When `Metadata` encounters EOF, it could be that there actually are

View on GitHub (pinned to 3653d2ed49)

Solutions

  1. Do not override log_format_version; keep the default that matches the on-disk data
  2. Inspect a segment header (byte 6 after the '(ds)^2' magic) to learn the on-disk version, then configure Options to match
  3. Migrate data: rewrite segments into the new format with a converter before switching versions
  4. Start a fresh commitlog directory for the new format after archiving the old one

Example fix

// before
let mut opts = Options::default();
opts.log_format_version = 2; // segments on disk were written as 1

// after
// keep the version that matches the on-disk segments
let opts = Options::default();
Defensive patterns

Strategy: validation

Validate before calling

// Read the on-disk version byte (offset 6, after the 6-byte magic) before opening
fn on_disk_version(path: &std::path::Path) -> io::Result<u8> {
    use std::io::Read as _;
    let mut f = std::fs::File::open(path)?;
    let mut buf = [0u8; segment::Header::LEN];
    f.read_exact(&mut buf)?;
    assert_eq!(&buf[..6], b"(ds)^2", "not a commitlog segment");
    Ok(buf[6])
}

Type guard

fn is_version_mismatch(err: &io::Error) -> bool {
    err.kind() == io::ErrorKind::InvalidData && err.to_string().contains("log format version mismatch")
}

Try / catch

match open_commitlog(&dir, &opts) {
    Ok(log) => Ok(log),
    Err(e) if is_version_mismatch(&e) => Err(friendly(e)), // surface 'pin Options::log_format_version to the segment version'
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@3653d2ed49 (2026-08-20). Data as JSON: /api/errors/2c114ba18128b8a4. Report an issue: GitHub.