{"record":{"id":"c1d7b1dcdaf34a6d","repo":"tursodatabase/turso","slug":"invalid-mvcc-logical-log-header-flags","errorCode":null,"errorMessage":"invalid MVCC logical log header flags","messagePattern":"invalid MVCC logical log header flags","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"cli/sync_server.rs","lineNumber":991,"sourceCode":"        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!(\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]);","sourceCodeStart":973,"sourceCodeEnd":1009,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/cli/sync_server.rs#L973-L1009","documentation":"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.","triggerScenarios":"Corrupted header bytes or a future lml3 revision that allocated new flag bits; hand-edited or partially overwritten log files.","commonSituations":"Storage corruption or interrupted writes hitting the header; log files produced by experimental engine builds that set extra header bits.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn header_flags_ok(path: &std::path::Path) -> Option<bool> {\n    let mut buf = [0u8; 6];\n    std::fs::File::open(path).ok()?.read_exact(&mut buf).ok()?;\n    Some(buf[5] & 0b1111_1110 == 0)\n}","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["Never hand-edit log header bytes.","Treat unknown header bits as corruption or a newer format; upgrade the server before serving such logs."],"tags":["mvcc","logical-log","header-flags","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"}