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 areView on GitHub (pinned to 3653d2ed49)
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
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
- 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
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
- no current segment, expected segment header
- all-zeroes commit header
- no valid commits in segment
- segment header does not start with magic: expected {:02x?},
- mismatched key in offset index file
AI-assisted analysis of clockworklabs/SpacetimeDB@3653d2ed49 (2026-08-20).
Data as JSON: /api/errors/2c114ba18128b8a4.
Report an issue: GitHub.