clockworklabs/SpacetimeDB · error · io::Error
failed to read {} bytes of commit payload: {}
Error message
failed to read {} bytes of commit payload: {} What it means
After a commit header decodes, the reader must read exactly `hdr.len` bytes of records. Failing to do so — almost always UnexpectedEof because the file ends early — is reported with the expected byte count and the underlying error. This signature means a commit was partially appended (the process or machine died mid-write), so the log is truncated after the previous commit.
Source
Thrown at crates/commitlog/src/commit.rs:314
/// [`ChecksumMismatch`] is returned.
pub fn decode<R: Read>(reader: R) -> io::Result<Option<Self>> {
Self::decode_internal(reader, DEFAULT_LOG_FORMAT_VERSION)
}
pub(crate) fn decode_internal<R: Read>(reader: R, log_format_version: u8) -> io::Result<Option<Self>> {
let mut reader = Crc32cReader::new(reader);
let v = if log_format_version == 0 {
Version::V0
} else {
Version::V1
};
let Some(hdr) = Header::decode_internal(&mut reader, v)? else {
return Ok(None);
};
let mut records = vec![0; hdr.len as usize];
reader.read_exact(&mut records).map_err(|e| {
io::Error::new(
e.kind(),
format!("failed to read {} bytes of commit payload: {}", hdr.len, e),
)
})?;
let chk = reader.crc32c();
let crc = decode_u32(reader.into_inner())
.map_err(|e| io::Error::new(e.kind(), format!("failed to read checksum: {e}")))?;
if chk != crc {
return Err(invalid_data(ChecksumMismatch));
}
Ok(Some(Self {
min_tx_offset: hdr.min_tx_offset,
epoch: hdr.epoch,
n: hdr.n,
records,View on GitHub (pinned to 524b4487d9)
Solutions
- Let SpacetimeDB recovery proceed — a torn final commit is truncated away and the committed prefix is exposed
- If the host refuses to open, restore the affected segment from backup or snapshot
- Fix the root cause: free disk space, avoid killing the host mid-commit, snapshot with the host stopped
Defensive patterns
Strategy: try-catch
Try / catch
match commit.decode(&mut reader) {
Ok(None) => break,
Ok(Some(c)) => commits.push(c),
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
// torn final commit: log is truncated; recover at the committed prefix
tracing::warn!("commitlog truncated mid-payload: {e}");
break;
}
Err(e) => return Err(e),
} Prevention
- Shut the host down gracefully before snapshots or backups
- Monitor disk space — a full disk mid-append tears the last commit
- Expect one torn tail commit after any hard crash; recovery is designed to handle it
When it happens
Trigger: Header decoded but the file ends before `hdr.len` record bytes can be read: process killed mid-append, disk-full abort, or a data directory copied while being written.
Common situations: Power loss or SIGKILL during a reducer commit; disk filling up during append; snapshots or rsync of db files while the host runs.
Related errors
- failed to read checksum: {e}
- error reading commit header: {e}
- InvalidData
- failed to read segment header ({} bytes): {}
- unexpected EOF while validating commit at byte offset {byte_
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/b25e9c42d3ade0d6.
Report an issue: GitHub.