{"record":{"id":"c1773bc5122c932f","repo":"tursodatabase/turso","slug":"mvcc-logical-log-header-checksum-mismatch","errorCode":null,"errorMessage":"MVCC logical log header checksum mismatch","messagePattern":"MVCC logical log header checksum mismatch","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"cli/sync_server.rs","lineNumber":1013,"sourceCode":"        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\"));\n    }\n    Ok(())\n}\n\nfn initial_mvcc_log_crc(log: &[u8]) -> Result<u32> {\n    let salt = u64::from_le_bytes(\n        log[MVCC_LOG_HEADER_SALT_START..MVCC_LOG_HEADER_SALT_END]\n            .try_into()\n            .expect(\"fixed-size salt slice\"),\n    );\n    Ok(crc32c::crc32c(&salt.to_le_bytes()))\n}\n\nfn read_mvcc_frame_boundary(\n    log: &[u8],\n    offset: usize,\n    running_crc: u32,\n) -> Result<Option<(usize, u32)>> {","sourceCodeStart":995,"sourceCodeEnd":1031,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/cli/sync_server.rs#L995-L1031","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nlet snapshot = scan_mvcc_log(&log)?; // errors: MVCC logical log header checksum mismatch\n\n// after: a broken header makes all deltas untrustworthy — re-bootstrap\nlet snapshot = match scan_mvcc_log(&log) {\n    Ok(snapshot) => snapshot,\n    Err(err) if err.to_string().contains(\"header checksum mismatch\") => {\n        std::fs::remove_file(&log_path)?;\n        rebootstrap_log_from_server()?\n    }\n    Err(err) => return Err(err),\n};","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match scan_mvcc_log(&log) {\n    Ok(snapshot) => { /* proceed */ }\n    Err(err) if err.to_string().contains(\"header checksum mismatch\") => {\n        // header untrustworthy -> discard local log and re-bootstrap fully;\n        // do not retry: the CRC is deterministic over the same bytes\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["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."],"tags":["mvcc","turso","sync","crc32c","corruption"],"backgroundTag":"checksum-mismatch","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}