tursodatabase/turso · error
MVCC logical log header checksum mismatch
Error message
MVCC logical log header checksum mismatch
What it means
The log header stores a CRC32C of itself at bytes 52-56, computed with the CRC field zeroed. validate_mvcc_log_header recomputes crc32c over bytes [0,56) with the CRC span zeroed and compares; a mismatch means the first 56 bytes changed after they were written. The running frame CRC chain is seeded from the header salt (initial_mvcc_log_crc), so an untrustworthy header would silently invalidate every later frame check, hence the hard rejection.
Source
Thrown at cli/sync_server.rs:1013
return Err(anyhow!(
"invalid MVCC logical log header length: {header_len}"
));
}
if log[MVCC_LOG_HEADER_RESERVED_START..MVCC_LOG_HEADER_CRC_START]
.iter()
.any(|byte| *byte != 0)
{
return Err(anyhow!(
"MVCC logical log header reserved bytes must be zero"
));
}
let stored_crc = read_u32_le(log, MVCC_LOG_HEADER_CRC_START)?;
let mut crc_buf = [0u8; MVCC_LOG_HEADER_SIZE];
crc_buf.copy_from_slice(&log[..MVCC_LOG_HEADER_SIZE]);
crc_buf[MVCC_LOG_HEADER_CRC_START..MVCC_LOG_HEADER_SIZE].fill(0);
let expected_crc = crc32c::crc32c(&crc_buf);
if stored_crc != expected_crc {
return Err(anyhow!("MVCC logical log header checksum mismatch"));
}
Ok(())
}
fn initial_mvcc_log_crc(log: &[u8]) -> Result<u32> {
let salt = u64::from_le_bytes(
log[MVCC_LOG_HEADER_SALT_START..MVCC_LOG_HEADER_SALT_END]
.try_into()
.expect("fixed-size salt slice"),
);
Ok(crc32c::crc32c(&salt.to_le_bytes()))
}
fn read_mvcc_frame_boundary(
log: &[u8],
offset: usize,
running_crc: u32,
) -> Result<Option<(usize, u32)>> {View on GitHub (pinned to bad083fafb)
Solutions
- Treat the log as corrupt: delete the local MVCC logical log and re-bootstrap with a full pull from the server instead of a delta pull.
- Verify transfer integrity by comparing sha256 of the log on producer and consumer.
- If mismatches recur on one node, check storage health (smartctl, dmesg I/O errors) — the corruption is local.
- Do not retry the same bytes; the CRC is deterministic and retrying cannot fix it.
Example fix
// before
let snapshot = scan_mvcc_log(&log)?; // errors: MVCC logical log header checksum mismatch
// after: a broken header makes all deltas untrustworthy — re-bootstrap
let snapshot = match scan_mvcc_log(&log) {
Ok(snapshot) => snapshot,
Err(err) if err.to_string().contains("header checksum mismatch") => {
std::fs::remove_file(&log_path)?;
rebootstrap_log_from_server()?
}
Err(err) => return Err(err),
}; Defensive patterns
Strategy: try-catch
Try / catch
match scan_mvcc_log(&log) {
Ok(snapshot) => { /* proceed */ }
Err(err) if err.to_string().contains("header checksum mismatch") => {
// header untrustworthy -> discard local log and re-bootstrap fully;
// do not retry: the CRC is deterministic over the same bytes
}
Err(err) => return Err(err),
} Prevention
- Verify transfers of the logical log with sha256 on both ends.
- Store the log on durable storage; investigate recurring CRC failures as hardware faults.
- Re-bootstrap (full pull) on any header integrity failure instead of serving deltas.
- When writing test log producers, compute the CRC over bytes [0,52) with the CRC span zeroed.
When it happens
Trigger: scan_mvcc_log on a log whose stored CRC at [52,56) does not equal crc32c of the rest of the header: any modification of the first 56 bytes after writing — partial overwrite, byte-level transfer corruption, disk bit rot, or a test producer computing the CRC over the wrong byte range (e.g. not zeroing the CRC field).
Common situations: Failing disks or unreliable network filesystems holding the logical log; crash mid-header write; copying logs between nodes without hash verification; hand-written test fixtures with an incorrect CRC computation.
Related errors
- MVCC logical log frame checksum mismatch at offset {offset}
- invalid MVCC logical log header length: {header_len}
- MVCC logical log header reserved bytes must be zero
- invalid MVCC logical log frame magic at offset {offset}: {fr
- unsupported MVCC logical log frame flags at offset {offset}:
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/c1773bc5122c932f.
Report an issue: GitHub.