tursodatabase/turso · error
invalid MVCC logical log header flags
Error message
invalid MVCC logical log header flags
What it means
Header byte 5 holds flags; only bit 0 is defined and the check `log[5] & 0b1111_1110 != 0` requires every other bit to be zero. A header with unknown bits set is treated as corrupt or from a future format and is rejected with HTTP 500 — unlike the version error, it gets no replace-base downgrade because only the 'unsupported ... version' message is considered a portable-fallback condition.
Source
Thrown at cli/sync_server.rs:991
end_offset: offset as u64,
crc_by_offset,
})
}
fn is_nonportable_mvcc_log_error(err: &anyhow::Error) -> bool {
let message = err.to_string();
message.starts_with("unsupported MVCC logical log version ")
}
fn validate_mvcc_log_header(log: &[u8]) -> Result<()> {
if read_u32_le(log, 0)? != MVCC_LOG_MAGIC {
return Err(anyhow!("invalid MVCC logical log magic"));
}
if log[4] != MVCC_LOG_VERSION {
return Err(anyhow!("unsupported MVCC logical log version {}", log[4]));
}
if log[5] & 0b1111_1110 != 0 {
return Err(anyhow!("invalid MVCC logical log header flags"));
}
let header_len = u16::from_le_bytes([log[6], log[7]]) as usize;
if header_len != MVCC_LOG_HEADER_SIZE {
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]);View on GitHub (pinned to bad083fafb)
Solutions
- Verify the .db-log's provenance: it must come from the same engine build as the server.
- Remove the unreadable log so the server's missing-file path serves replace-base pages and clients re-bootstrap.
- If the flags are legitimate (newer format), upgrade the server to a build that understands them.
Defensive patterns
Strategy: validation
Validate before calling
fn header_flags_ok(path: &std::path::Path) -> Option<bool> {
let mut buf = [0u8; 6];
std::fs::File::open(path).ok()?.read_exact(&mut buf).ok()?;
Some(buf[5] & 0b1111_1110 == 0)
} Try / catch
On 500 'invalid MVCC logical log header flags', treat the log as unreadable: verify provenance, remove it to trigger the replace-base fallback, and re-bootstrap clients rather than retrying.
Prevention
- Never hand-edit log header bytes.
- Treat unknown header bits as corruption or a newer format; upgrade the server before serving such logs.
When it happens
Trigger: Corrupted header bytes or a future lml3 revision that allocated new flag bits; hand-edited or partially overwritten log files.
Common situations: Storage corruption or interrupted writes hitting the header; log files produced by experimental engine builds that set extra header bits.
Related errors
- truncated MVCC logical log header: len={} header_size={}
- invalid MVCC logical log magic
- unsupported MVCC logical log version {}
- MVCC logical pull revision is from the future: client_offset
- MVCC logical pull offset is not a transaction boundary: {off
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/c1d7b1dcdaf34a6d.
Report an issue: GitHub.