{"record":{"id":"fbc1bb1637e1c611","repo":"tursodatabase/turso","slug":"invalid-mvcc-logical-log-header-length-header-le","errorCode":null,"errorMessage":"invalid MVCC logical log header length: {header_len}","messagePattern":"invalid MVCC logical log header length: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"cli/sync_server.rs","lineNumber":995,"sourceCode":"\nfn is_nonportable_mvcc_log_error(err: &anyhow::Error) -> bool {\n    let message = err.to_string();\n    message.starts_with(\"unsupported MVCC logical log version \")\n}\n\nfn validate_mvcc_log_header(log: &[u8]) -> Result<()> {\n    if read_u32_le(log, 0)? != MVCC_LOG_MAGIC {\n        return Err(anyhow!(\"invalid MVCC logical log magic\"));\n    }\n    if log[4] != MVCC_LOG_VERSION {\n        return Err(anyhow!(\"unsupported MVCC logical log version {}\", log[4]));\n    }\n    if log[5] & 0b1111_1110 != 0 {\n        return Err(anyhow!(\"invalid MVCC logical log header flags\"));\n    }\n    let header_len = u16::from_le_bytes([log[6], log[7]]) as usize;\n    if header_len != MVCC_LOG_HEADER_SIZE {\n        return Err(anyhow!(\n            \"invalid MVCC logical log header length: {header_len}\"\n        ));\n    }\n    if log[MVCC_LOG_HEADER_RESERVED_START..MVCC_LOG_HEADER_CRC_START]\n        .iter()\n        .any(|byte| *byte != 0)\n    {\n        return Err(anyhow!(\n            \"MVCC logical log header reserved bytes must be zero\"\n        ));\n    }\n    let stored_crc = read_u32_le(log, MVCC_LOG_HEADER_CRC_START)?;\n    let mut crc_buf = [0u8; MVCC_LOG_HEADER_SIZE];\n    crc_buf.copy_from_slice(&log[..MVCC_LOG_HEADER_SIZE]);\n    crc_buf[MVCC_LOG_HEADER_CRC_START..MVCC_LOG_HEADER_SIZE].fill(0);\n    let expected_crc = crc32c::crc32c(&crc_buf);\n    if stored_crc != expected_crc {\n        return Err(anyhow!(\"MVCC logical log header checksum mismatch\"));","sourceCodeStart":977,"sourceCodeEnd":1013,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/cli/sync_server.rs#L977-L1013","documentation":"The MVCC logical log begins with a fixed 56-byte header (MVCC_LOG_HEADER_SIZE). Bytes 6-8 hold a little-endian u16 header length that must equal 56; validate_mvcc_log_header throws when any other value is present. The magic (0x4C4D4C32), version (3), and flags checks run first, so reaching this error means the file claims to be a current MVCC log but encodes a different header layout, and the scanner refuses to misread field offsets.","triggerScenarios":"scan_mvcc_log(&log) on a log whose bytes 6-8 decode to anything other than 56: a log written by an experimental or divergent build with a changed header size, a header corrupted after writing, or a hand-built test fixture that filled the length field incorrectly.","commonSituations":"Sync client and server built from different Turso revisions during a rolling upgrade; experimental MVCC format iterations that kept version=3 but changed header layout; the wrong file copied over the logical log path; truncated-then-repaired copies that garbled the middle of the header.","solutions":["Re-pull or regenerate the MVCC logical log from the producer; a header-length mismatch means the local copy cannot be parsed safely.","Hexdump the first 56 bytes (xxd -l 56 <log>) and verify the magic 0x4C4D4C32 at offset 0 and the u16 at offsets 6-8 equals 56 (0x38).","Confirm writer and reader run the same engine build (56-byte header, MVCC_LOG_VERSION 3) and upgrade the older side.","Check the file was not mixed up or partially copied: compare size and hash against the producer's log."],"exampleFix":"// before\nlet snapshot = scan_mvcc_log(&log)?; // errors: invalid MVCC logical log header length\n\n// after: verify the header layout before scanning, then re-pull on mismatch\nfn mvcc_header_length_ok(log: &[u8]) -> bool {\n    log.len() >= MVCC_LOG_HEADER_SIZE\n        && u16::from_le_bytes([log[6], log[7]]) as usize == MVCC_LOG_HEADER_SIZE\n}\nif !mvcc_header_length_ok(&log) {\n    std::fs::remove_file(&log_path)?;\n    return rebootstrap_log_from_server();\n}\nlet snapshot = scan_mvcc_log(&log)?;","handlingStrategy":"validation","validationCode":"const MVCC_LOG_HEADER_SIZE: usize = 56;\nfn mvcc_header_length_ok(log: &[u8]) -> bool {\n    log.len() >= MVCC_LOG_HEADER_SIZE\n        && u16::from_le_bytes([log[6], log[7]]) as usize == MVCC_LOG_HEADER_SIZE\n}\n// run before scan_mvcc_log:\nif !mvcc_header_length_ok(&log) {\n    anyhow::bail!(\"log header length is not {MVCC_LOG_HEADER_SIZE}; re-pull the log\");\n}","typeGuard":"fn mvcc_header_length_ok(log: &[u8]) -> bool {\n    log.len() >= MVCC_LOG_HEADER_SIZE\n        && u16::from_le_bytes([log[6], log[7]]) as usize == MVCC_LOG_HEADER_SIZE\n}","tryCatchPattern":"match scan_mvcc_log(&log) {\n    Ok(snapshot) => { /* serve deltas from crc_by_offset */ }\n    Err(err) if err.to_string().contains(\"invalid MVCC logical log header length\") => {\n        // deterministic format error: re-bootstrap, never retry the same bytes\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Pin writer and reader to the same tursodb build when using MVCC sync.","Verify log copies with a hash (sha256) before pointing the sync server at them.","Never hand-edit, pad, or concatenate MVCC logical log files.","Zero the full 56-byte header before filling fields when building test logs."],"tags":["mvcc","turso","sync","file-format","log-header"],"backgroundTag":"file-format-validation-failed","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}