tursodatabase/turso · error · anyhow::Error
MVCC logical log extension block missing flag at offset
Error message
MVCC logical log extension block missing flag at offset {offset} What it means
The mirror invariant of error 769: a nonzero extension-block size requires MVCC_TX_FRAME_FLAG_HAS_EXTENSION_BLOCK to be set in the frame flags word at offset+36. A block present without its flag means the frame layout and its metadata disagree, so the reader stops.
Solutions
- Restore or regenerate the MVCC log
- If forking the writer, set MVCC_TX_FRAME_FLAG_HAS_EXTENSION_BLOCK whenever a block is emitted and cover it with a round-trip test
Defensive patterns
Strategy: try-catch
Try / catch
let snapshot = match scan_mvcc_log(&log) {
Ok(s) => s,
Err(err) if err.to_string().contains("extension block missing flag") => {
restore_or_rebuild()?
}
Err(err) => return Err(err),
}; Prevention
- Set MVCC_TX_FRAME_FLAG_HAS_EXTENSION_BLOCK in the writer whenever a block is emitted
- Add writer-side assertions that fail fast on inconsistent frames
- Test mixed workloads with and without extension blocks
When it happens
Trigger: read_mvcc_frame_boundary computes extension_size > 0 while frame_flags & MVCC_TX_FRAME_FLAG_HAS_EXTENSION_BLOCK == 0 on an extension frame.
Common situations: A writer that appends extension blocks but forgets to set the flag (fork bug); corruption that cleared the flag bit; mixed logs produced by two different writer versions.
Related errors
- MVCC logical log extension record count without extension…
- invalid MVCC logical log frame end magic at offset
- invalid MVCC logical log frame magic at offset
- invalid MVCC logical log header flags
- invalid MVCC logical log header length
AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-08-20).
Data as JSON: /api/errors/bb1ba6d765b7d818.
Report an issue: GitHub.
Appendix: source
Thrown at cli/sync_server.rs:1183
let payload_size = usize::try_from(read_u64_le(log, offset + 4)?)
.map_err(|_| anyhow!("MVCC logical log payload size overflows usize"))?;
let extension_size = if has_extension_header {
let extension_size = usize::try_from(read_u64_le(log, offset + 24)?)
.map_err(|_| anyhow!("MVCC logical log extension size overflows usize"))?;
let extension_record_count = read_u32_le(log, offset + 32)?;
let frame_flags = read_u32_le(log, offset + 36)?;
if frame_flags & !MVCC_TX_FRAME_FLAG_HAS_EXTENSION_BLOCK != 0 {
return Err(anyhow!(
"unsupported MVCC logical log frame flags at offset {offset}: {frame_flags:#x}"
));
}
if extension_size == 0 && extension_record_count != 0 {
return Err(anyhow!(
"MVCC logical log extension record count without extension block at offset {offset}"
));
}
if extension_size > 0 && frame_flags & MVCC_TX_FRAME_FLAG_HAS_EXTENSION_BLOCK == 0 {
return Err(anyhow!(
"MVCC logical log extension block missing flag at offset {offset}"
));
}
extension_size
} else {
0
};
let trailer_start = offset
.checked_add(header_size)
.and_then(|value| value.checked_add(payload_size))
.and_then(|value| value.checked_add(extension_size))
.ok_or_else(|| anyhow!("MVCC logical log frame offset overflow"))?;
let frame_end = trailer_start
.checked_add(MVCC_TX_TRAILER_SIZE)
.ok_or_else(|| anyhow!("MVCC logical log frame end overflow"))?;
if frame_end > log.len() {
return Ok(None);
}View on GitHub (pinned to 492c4a71cd)