{"record":{"id":"d943a6722691a863","repo":"clockworklabs/SpacetimeDB","slug":"failed-to-read-checksum-e","errorCode":null,"errorMessage":"failed to read checksum: {e}","messagePattern":"failed to read checksum: (.+?)","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/commitlog/src/commit.rs","lineNumber":322,"sourceCode":"        let v = if log_format_version == 0 {\n            Version::V0\n        } else {\n            Version::V1\n        };\n        let Some(hdr) = Header::decode_internal(&mut reader, v)? else {\n            return Ok(None);\n        };\n        let mut records = vec![0; hdr.len as usize];\n        reader.read_exact(&mut records).map_err(|e| {\n            io::Error::new(\n                e.kind(),\n                format!(\"failed to read {} bytes of commit payload: {}\", hdr.len, e),\n            )\n        })?;\n\n        let chk = reader.crc32c();\n        let crc = decode_u32(reader.into_inner())\n            .map_err(|e| io::Error::new(e.kind(), format!(\"failed to read checksum: {e}\")))?;\n\n        if chk != crc {\n            return Err(invalid_data(ChecksumMismatch));\n        }\n\n        Ok(Some(Self {\n            min_tx_offset: hdr.min_tx_offset,\n            epoch: hdr.epoch,\n            n: hdr.n,\n            records,\n            checksum: crc,\n        }))\n    }\n\n    /// Convert `self` into an iterator yielding [`Transaction`]s.\n    ///\n    /// The supplied [`Decoder`] is responsible for extracting individual\n    /// transactions from the `records` buffer.","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/commitlog/src/commit.rs#L304-L340","documentation":"A commit ends with a 4-byte CRC32C checksum after its records; failing to read those bytes (the error kind is preserved in the message) means the file ends or errors between payload and checksum. It is the same torn-write family as the payload-read error, landing exactly at the checksum boundary of the final commit.","triggerScenarios":"Records read successfully but the trailing 4-byte CRC cannot be read: the last commit was written up to or into its checksum and then cut off.","commonSituations":"Same scenarios as a truncated payload — hard crash mid-commit, disk full, copying db files while the host writes — landing at the checksum boundary.","solutions":["Same as a truncated payload: let recovery truncate the incomplete final commit and open at the prefix","Restore from backup if the repository will not open","Prevent torn writes: graceful shutdown, disk space monitoring, consistent snapshots"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match commit.decode(&mut reader) {\n    Ok(None) => break,\n    Ok(Some(c)) => commits.push(c),\n    Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {\n        // checksum never arrived: final commit is incomplete; the prefix up to the\n        // previous commit is still valid\n        tracing::warn!(\"commitlog truncated before checksum: {e}\");\n        break;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use graceful shutdowns so the final commit is always fully written","Take snapshots only while the host is stopped or via a consistent mechanism","Treat any truncation warning after a crash as expected; treat repeated ones as a disk problem"],"tags":["rust","io","commitlog","truncation","crash-recovery"],"backgroundTag":"truncated-log-read","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}