{"record":{"id":"96f42920d8ab5471","repo":"tursodatabase/turso","slug":"invalid-mvcc-logical-log-magic","errorCode":null,"errorMessage":"invalid MVCC logical log magic","messagePattern":"invalid MVCC logical log magic","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"cli/sync_server.rs","lineNumber":985,"sourceCode":"        running_crc = frame_crc;\n        offset = frame_end;\n        crc_by_offset.push((offset as u64, running_crc));\n    }\n\n    Ok(MvccLogSnapshot {\n        end_offset: offset as u64,\n        crc_by_offset,\n    })\n}\n\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!(","sourceCodeStart":967,"sourceCodeEnd":1003,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/cli/sync_server.rs#L967-L1003","documentation":"The first four bytes of the .db-log must equal MVCC_LOG_MAGIC 0x4C4D4C32; anything else means the file at the .db-log path is not an lml3 MVCC logical log. Unlike the version-mismatch error, a bad magic is not treated as a 'portable' fallback case (is_nonportable_mvcc_log_error only matches the version message), so it surfaces as a hard HTTP 500.","triggerScenarios":"A foreign or corrupt file at the .db-log path: another database's log, a text file, bit rot, or a format whose magic differs; the header check runs before any fallback logic can downgrade the error.","commonSituations":"Swapping or misplacing sync files between databases; a different tool writing a file with the same name; storage-level corruption.","solutions":["Confirm the .db-log sitting next to the .db was written by the same engine and run (check the first bytes).","Remove the wrong file: the server falls back to replace-base pages and clients re-bootstrap.","Recreate the sync setup (.db plus .db-log) from a consistent source."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn is_lml3_log(path: &std::path::Path) -> bool {\n    let mut magic = [0u8; 4];\n    std::fs::File::open(path)\n        .and_then(|mut f| std::io::Read::read_exact(&mut f, &mut magic))\n        .map(|_| u32::from_le_bytes(magic) == 0x4C4D4C32)\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"On 500 'invalid MVCC logical log magic', do not retry: verify the file at the .db-log path belongs to this database; remove or replace it so the server serves replace-base pages.","preventionTips":["Never place foreign files at the .db-log path.","Verify magic and version bytes with tooling that manipulates sync files.","Keep one .db-log per .db and never copy logs between databases."],"tags":["mvcc","logical-log","magic-bytes","corruption","file-format"],"backgroundTag":"corrupt-log-file","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}