tursodatabase/turso · error · anyhow::Error
buffer too short for u32 at offset {offset}
Error message
buffer too short for u32 at offset {offset} What it means
read_u32_le reads 4 little-endian bytes at an offset using slice::get and returns this error when offset..offset+4 leaves the buffer. Inside the log scanner it is defensive: every caller pre-verifies lengths (log.len() >= 56 before header validation, header+trailer size checks before frame reads), so hitting it there indicates a regression. New call sites must bound-check before calling.
Source
Thrown at cli/sync_server.rs:1106
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)))
}
fn read_u32_le(buf: &[u8], offset: usize) -> Result<u32> {
let bytes = buf
.get(offset..offset + 4)
.ok_or_else(|| anyhow!("buffer too short for u32 at offset {offset}"))?;
Ok(u32::from_le_bytes(bytes.try_into().unwrap()))
}
fn read_u64_le(buf: &[u8], offset: usize) -> Result<u64> {
let bytes = buf
.get(offset..offset + 8)
.ok_or_else(|| anyhow!("buffer too short for u64 at offset {offset}"))?;
Ok(u64::from_le_bytes(bytes.try_into().unwrap()))
}
fn current_db_size_pages(conn: &Connection, max_frame: u64) -> Result<u64> {
if max_frame > 0 {
let frame_size = WAL_FRAME_HEADER_SIZE + PAGE_SIZE;
let mut last_frame = vec![0u8; frame_size];
let last_info = conn.wal_get_frame(max_frame, &mut last_frame)?;
Ok(last_info.db_size as u64)
} else {
Ok(0)View on GitHub (pinned to bad083fafb)
Solutions
- Check buf.len() >= offset + 4 before calling read_u32_le.
- Compute the bound with offset.checked_add(4) so a huge offset cannot silently wrap.
- If this fires inside scan_mvcc_log on a length-checked buffer, file a bug — the invariant broke.
- Keep read helpers private and always pair them with explicit size assertions at the call site.
Example fix
// before
let magic = read_u32_le(buf, offset)?; // may error: buffer too short for u32
// after
anyhow::ensure!(
offset.checked_add(4).is_some_and(|end| end <= buf.len()),
"no room for u32 at offset {offset}"
);
let magic = read_u32_le(buf, offset)?; Defensive patterns
Strategy: validation
Validate before calling
fn has_u32_at(buf: &[u8], offset: usize) -> bool {
offset.checked_add(4).is_some_and(|end| end <= buf.len())
}
// before reading:
anyhow::ensure!(has_u32_at(buf, offset), "no room for u32 at offset {offset}");
let value = read_u32_le(buf, offset)?; Type guard
fn has_u32_at(buf: &[u8], offset: usize) -> bool {
offset.checked_add(4).is_some_and(|end| end <= buf.len())
} Try / catch
match read_u32_le(buf, offset) {
Ok(value) => { /* use value */ }
Err(err) if err.to_string().contains("buffer too short for u32") => {
// caller bug: fix the missing length pre-check, do not retry
}
Err(err) => return Err(err),
} Prevention
- Always verify the buffer covers offset+N before any fixed-width read.
- Compute bounds with checked_add so huge offsets cannot wrap.
- Keep read helpers private; expose APIs that take pre-validated slices.
- Add debug_assert! length invariants at call sites in debug builds.
When it happens
Trigger: read_u32_le(buf, offset) with fewer than 4 bytes remaining at offset (or an offset large enough that offset+4 itself overflows) — a caller that skipped its length pre-check, or refactored code that invalidated a previously proven invariant.
Common situations: New code paths using the helpers on short buffers; refactors that moved or removed size pre-checks; fuzzing the reader with truncated inputs; off-by-one errors in offset math computed by the caller.
Related errors
- buffer too short for u64 at offset {offset}
- Failed to register completion extension
- Error retrieving columns for view '{}': {}
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/41a0118c497dd7cc.
Report an issue: GitHub.