{"record":{"id":"c0153e25c2bb3cbb","repo":"spacejam/sled","slug":"crc-mismatch-data-corruption-detected","errorCode":null,"errorMessage":"crc mismatch - data corruption detected","messagePattern":"crc mismatch - data corruption detected","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/heap.rs","lineNumber":532,"sourceCode":"        _guard: &mut Guard<'_, DeferredFree, 16, 16>,\n    ) -> io::Result<Vec<u8>> {\n        log::trace!(\"reading from slot {} in slab {}\", slot, self.slot_size);\n\n        let mut data = Vec::with_capacity(self.slot_size);\n        unsafe {\n            data.set_len(self.slot_size);\n        }\n\n        let whence = self.slot_size as u64 * slot;\n\n        maybe!(sys_io::read_exact_at(&self.file, &mut data, whence))?;\n\n        let hash_actual: [u8; 4] =\n            (crc32fast::hash(&data[..self.slot_size - 4]) ^ 0xAF).to_le_bytes();\n        let hash_expected = &data[self.slot_size - 4..];\n\n        if hash_expected != hash_actual {\n            return Err(annotate!(io::Error::new(\n                io::ErrorKind::InvalidData,\n                \"crc mismatch - data corruption detected\"\n            )));\n        }\n\n        let len: usize = if self.slot_size <= u8::MAX as usize {\n            // crc32 + 1 byte frame\n            usize::from(data[self.slot_size - 5])\n        } else if self.slot_size <= u16::MAX as usize {\n            // crc32 + 2 byte frame\n            let mut size_bytes: [u8; 2] = [0; 2];\n            size_bytes\n                .copy_from_slice(&data[self.slot_size - 6..self.slot_size - 4]);\n            usize::from(u16::from_le_bytes(size_bytes))\n        } else if self.slot_size <= u32::MAX as usize {\n            // crc32 + 4 byte frame\n            let mut size_bytes: [u8; 4] = [0; 4];\n            size_bytes","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/spacejam/sled/blob/e449d17111f4a097e1c66b6db241962ccb6a4136/src/heap.rs#L514-L550","documentation":"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.","triggerScenarios":"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.","commonSituations":"Unclean shutdown recovery hitting a partially written slot; failing SSD/HDD sectors; editing or patching database files by hand; copying files mid-write.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// preflight: ensure the db directory is not being modified and the file size is stable\nlet size1 = std::fs::metadata(&path)?.len();\nstd::thread::sleep(std::time::Duration::from_millis(50));\nlet size2 = std::fs::metadata(&path)?.len();\nif size1 != size2 { return Err(anyhow!(\"db file changing under us\")); }","typeGuard":null,"tryCatchPattern":"match Db::open(&path) {\n    Ok(db) => db,\n    Err(e) if e.to_string().contains(\"crc mismatch\") => {\n        restore_from_backup(&path)?; // corruption cannot be repaired in place\n        Db::open(&path)?\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["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"],"tags":["rust","corruption","crc","storage"],"backgroundTag":"checksum-mismatch","analyzedSha":"e449d17111f4a097e1c66b6db241962ccb6a4136","analyzedAt":"2026-09-12T01:23:10.985Z","contentChangedAt":"2026-09-12T01:23:10.985Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}