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
- Restore from backup; the affected slot is corrupt and cannot be self-repaired
- Run storage diagnostics (SMART, fsck) to find and mitigate failing media
- If recovery tooling exists, export what is readable and re-import into a fresh database
- 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
- Keep tested backups; CRC failures are unrecoverable in place
- Use ECC/storage with write barriers; avoidsuspect drives
- Never edit database files externally
- Snapshot only after clean shutdown
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
- encountered corrupted settings cookie with mismatched CRC.
- corrupt frame length
- crc mismatch for read of batch frame
- failed to fill whole buffer
- failed to write whole buffer
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_bytesView on GitHub (pinned to e449d17111)