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

  1. Restore or regenerate the MVCC log
  2. 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

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


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)