spacejam/sled · critical

crc mismatch - data corruption detected

Error message

crc mismatch - data corruption detected

What it means

Each heap slot stores a CRC32 (xored with 0xAF) over its payload; on read, the recomputed CRC must match the trailing 4 bytes. A mismatch means the stored data bytes were altered after being written, so the read fails with InvalidData rather than returning corrupt data.

Solutions

  1. Restore from backup; the affected slot is corrupt and cannot be self-repaired
  2. Run storage diagnostics (SMART, fsck) to find and mitigate failing media
  3. If recovery tooling exists, export what is readable and re-import into a fresh database
  4. Recreate the database from an authoritative upstream source if backup is unavailable
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: ensure the db directory is not being modified and the file size is stable
let size1 = std::fs::metadata(&path)?.len();
std::thread::sleep(std::time::Duration::from_millis(50));
let size2 = std::fs::metadata(&path)?.len();
if size1 != size2 { return Err(anyhow!("db file changing under us")); }

Try / catch

match Db::open(&path) {
    Ok(db) => db,
    Err(e) if e.to_string().contains("crc mismatch") => {
        restore_from_backup(&path)?; // corruption cannot be repaired in place
        Db::open(&path)?
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Reading a page/slot whose payload bytes changed on disk: bit rot, torn writes during power loss, corruption from external modification of the file, or reading garbage in a region not actually written by this database.

Common situations: Unclean shutdown recovery hitting a partially written slot; failing SSD/HDD sectors; editing or patching database files by hand; copying files mid-write.

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/c0153e25c2bb3cbb. Report an issue: GitHub.

Appendix: source

Thrown at src/heap.rs:532

        _guard: &mut Guard<'_, DeferredFree, 16, 16>,
    ) -> io::Result<Vec<u8>> {
        log::trace!("reading from slot {} in slab {}", slot, self.slot_size);

        let mut data = Vec::with_capacity(self.slot_size);
        unsafe {
            data.set_len(self.slot_size);
        }

        let whence = self.slot_size as u64 * slot;

        maybe!(sys_io::read_exact_at(&self.file, &mut data, whence))?;

        let hash_actual: [u8; 4] =
            (crc32fast::hash(&data[..self.slot_size - 4]) ^ 0xAF).to_le_bytes();
        let hash_expected = &data[self.slot_size - 4..];

        if hash_expected != hash_actual {
            return Err(annotate!(io::Error::new(
                io::ErrorKind::InvalidData,
                "crc mismatch - data corruption detected"
            )));
        }

        let len: usize = if self.slot_size <= u8::MAX as usize {
            // crc32 + 1 byte frame
            usize::from(data[self.slot_size - 5])
        } else if self.slot_size <= u16::MAX as usize {
            // crc32 + 2 byte frame
            let mut size_bytes: [u8; 2] = [0; 2];
            size_bytes
                .copy_from_slice(&data[self.slot_size - 6..self.slot_size - 4]);
            usize::from(u16::from_le_bytes(size_bytes))
        } else if self.slot_size <= u32::MAX as usize {
            // crc32 + 4 byte frame
            let mut size_bytes: [u8; 4] = [0; 4];
            size_bytes

View on GitHub (pinned to e449d17111)