spacejam/sled · error

crc mismatch for read of batch frame

Error message

crc mismatch for read of batch frame

What it means

After the frame length, read_frame reads the payload plus a trailing CRC and verifies it. If the recorded CRC differs from the CRC computed over the payload, the batch frame's contents are corrupt and it is rejected (after logging a warning) instead of being applied.

Solutions

  1. Restore metadata/log files from backup, or let the system rebuild them from other durable state if possible
  2. Remove/rename the corrupt log segment so recovery can resynchronize from earlier valid frames (accepting data loss for that segment)
  3. Check storage health (SMART/fsck) and fix underlying hardware issues
  4. Recreate or re-import the database if corruption is widespread
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure sufficient free space and that the log directory is writable before opening
let stat = nix::sys::statvfs::stat(&path)?;
if stat.blocks_available < min_free_blocks { return Err(anyhow!("insufficient space for metadata writes")); }

Try / catch

match Db::open(&path) {
    Ok(db) => db,
    Err(e) if e.to_string().contains("crc mismatch for read of batch frame") => {
        // payload corrupted: restore metadata backup or rebuild segment
        repair_or_restore_metadata(&path)?;
        Db::open(&path)?
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Reading a metadata log/snapshot batch whose payload bytes were modified after write: torn write during a crash, bit rot, or partial disk flush.

Common situations: Power loss mid-write during metadata persistence; failing drives; interrupted file copies of the database directory.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of spacejam/sled@e449d17111 (2026-09-12). Data as JSON: /api/errors/402eeb60057d6a2d. Report an issue: GitHub.

Appendix: source

Thrown at src/metadata_store.rs:545

    reusable_frame_buffer.reserve(len + 12);
    unsafe {
        reusable_frame_buffer.set_len(len + 12);
    }
    reusable_frame_buffer[..8].copy_from_slice(&frame_size_with_crc_buf);

    fallible!(file.read_exact(&mut reusable_frame_buffer[8..]));

    let crc_actual = crc32fast::hash(&reusable_frame_buffer[..len + 8]) ^ 0xAF;
    let crc_recorded = u32::from_le_bytes([
        reusable_frame_buffer[len + 8],
        reusable_frame_buffer[len + 9],
        reusable_frame_buffer[len + 10],
        reusable_frame_buffer[len + 11],
    ]);

    if crc_actual != crc_recorded {
        log::warn!("encountered incorrect crc for batch in log");
        return Err(annotate!(io::Error::new(
            io::ErrorKind::InvalidData,
            "crc mismatch for read of batch frame",
        )));
    }

    let mut ret = vec![];

    let mut decoder = ZstdDecoder::new(&reusable_frame_buffer[8..len + 8])
        .expect("failed to create zstd decoder");

    let mut object_id_buf: [u8; 8] = [0; 8];
    let mut collection_id_buf: [u8; 8] = [0; 8];
    let mut location_buf: [u8; 8] = [0; 8];
    let mut low_key_len_buf: [u8; 8] = [0; 8];
    let mut low_key_buf = vec![];
    loop {
        let first_read_res = decoder
            .read_exact(&mut object_id_buf)

View on GitHub (pinned to e449d17111)