tursodatabase/turso · error · anyhow::Error

MVCC logical log frame end overflow

Error message

MVCC logical log frame end overflow

What it means

The final bound computation adds the 8-byte trailer (MVCC_TX_TRAILER_SIZE) to the already-computed trailer_start with checked_add. Overflow requires the previous sum to sit within 8 bytes of usize::MAX, which only corrupted length metadata produces. The guard exists so the subsequent frame_end > log.len() comparison is always done on valid arithmetic.

Source

Thrown at cli/sync_server.rs:1083

            ));
        }
        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);
    }
    let expected_crc = crc32c::crc32c_append(running_crc, &log[offset..trailer_start]);
    let stored_crc = read_u32_le(log, trailer_start)?;
    if stored_crc != expected_crc {
        return Err(anyhow!(
            "MVCC logical log frame checksum mismatch at offset {offset}"
        ));
    }
    let end_magic = read_u32_le(log, trailer_start + 4)?;
    if end_magic != MVCC_TX_END_MAGIC {
        return Err(anyhow!(
            "invalid MVCC logical log frame end magic at offset {offset}"
        ));
    }
    Ok(Some((frame_end, stored_crc)))
}

View on GitHub (pinned to bad083fafb)

Solutions

  1. Re-pull the log; trailer arithmetic overflow indicates corrupted length fields.
  2. Use a 64-bit build for the sync server.
  3. Add a plausibility pre-check bounding payload and extension sizes by the log length.
Defensive patterns

Strategy: try-catch

Try / catch

match scan_mvcc_log(&log) {
    Ok(snapshot) => { /* serve deltas */ }
    Err(err) if err.to_string().contains("frame end overflow") => {
        // same corrupt-length scenario as the offset overflow: re-pull the log
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: trailer_start within 8 bytes of usize::MAX after offset + header + payload + extension summed successfully — effectively the same corrupted-length scenario as the offset overflow, shifted by 8 bytes.

Common situations: Fuzzed log files engineered to make lengths just under usize::MAX; corrupted u64 length fields on any build; 32-bit builds with sizes near 4 GiB.

Related errors


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/92da21594cbad814. Report an issue: GitHub.