{"record":{"id":"ba3cf912c2c3fb36","repo":"clockworklabs/SpacetimeDB","slug":"error-reading-commit-header-e","errorCode":null,"errorMessage":"error reading commit header: {e}","messagePattern":"error reading commit header: (.+?)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/commitlog/src/commit.rs","lineNumber":92,"sourceCode":"\n                Ok(Some(Self {\n                    min_tx_offset,\n                    epoch: Commit::DEFAULT_EPOCH,\n                    n,\n                    len,\n                }))\n            }\n        }\n    }\n\n    fn decode_v1<R: Read>(mut reader: R) -> io::Result<Option<Self>> {\n        let mut hdr = [0; Self::LEN];\n        if let Err(e) = reader.read_exact(&mut hdr) {\n            if e.kind() == io::ErrorKind::UnexpectedEof {\n                return Ok(None);\n            }\n\n            return Err(io::Error::new(e.kind(), format!(\"error reading commit header: {e}\")));\n        }\n        match &mut hdr.as_slice() {\n            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => Ok(None),\n            buf => {\n                let min_tx_offset = buf.get_u64().map_err(|e| decode_header_error(e, \"min_tx_offset\"))?;\n                let epoch = buf.get_u64().map_err(|e| decode_header_error(e, \"epoch\"))?;\n                let n = buf.get_u16().map_err(|e| decode_header_error(e, \"n\"))?;\n                let len = buf.get_u32().map_err(|e| decode_header_error(e, \"len\"))?;\n\n                Ok(Some(Self {\n                    min_tx_offset,\n                    epoch,\n                    n,\n                    len,\n                }))\n            }\n        }\n    }","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/9e0d92412ff2248f401a8ad12d535f2b5ac30912/crates/commitlog/src/commit.rs#L74-L110","documentation":"Low-level commitlog error raised while decoding a commit header (Header::decode_v1 in the commitlog crate). The decoder reads the fixed-size v1 header (Header::LEN = 22 bytes: min_tx_offset u64, epoch u64, n u16, len u32); a clean end-of-file at that boundary is normal and returns Ok(None) so preallocated zeroed segments are allowed. Any other I/O failure is re-wrapped with this message, preserving the underlying io::ErrorKind.","triggerScenarios":"Replaying or opening a commitlog segment when the storage read fails partway through the header byte range with something other than UnexpectedEof - e.g. PermissionDenied, device/IO errors, or a failing network filesystem under the data directory.","commonSituations":"Data-directory permissions changed under a running node; failing or disconnecting disks/NFS; another process truncating or deleting segment files during replay.","solutions":["Check the data directory: permissions on segment files, disk health (dmesg/SMART), free space.","Ensure no second process (another node, a truncating backup job, manual tooling) mutates segment files while the log is being read.","If the media is damaged, restore the commitlog directory from a snapshot or replica."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Fail fast if segment files are not readable before replay\nlet meta = std::fs::metadata(&segment_path)?;\nanyhow::ensure!(meta.permissions().readonly() == false, \"segment file is read-only\");","typeGuard":null,"tryCatchPattern":"match Header::decode(&mut reader) {\n    Ok(Some(hdr)) => { /* process commit */ }\n    Ok(None) => {} // clean end of log (EOF at header boundary or zeroed preallocated bytes)\n    Err(e) => {\n        // UnexpectedEof is already normalized to Ok(None) by the library;\n        // anything reaching here is a real storage fault - surface it, do not retry blindly.\n        return Err(e.into());\n    }\n}","preventionTips":["Keep the commitlog data directory on local durable storage, not NFS/network volumes.","Grant the node process stable ownership of its data directory; never chmod or chown underneath it while running.","Monitor the storage layer for IO errors - this error is a symptom of a lower-level fault, not the disease."],"tags":["rust","commitlog","io","storage","header"],"backgroundTag":"disk-read-error","analyzedSha":"9e0d92412ff2248f401a8ad12d535f2b5ac30912","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}