clockworklabs/SpacetimeDB · error · io::Error
all-zeroes commit header
Error message
all-zeroes commit header
What it means
While decoding the mirrored stream, the fixed-size commit header was read successfully but decoded as all zeroes, which commit::Header::decode rejects (EOF was already handled just above). Zero regions typically come from preallocated-but-unwritten file space or a torn write on the producer side, so the stream contains filler instead of commit data.
Solutions
- Stream only up to the last valid commit: bound the read to the committed length from segment metadata, not the file size
- Trim trailing invalid data on the source before streaming (the OnTrailingData hook used at StreamWriter::create exists for this)
- On the consumer, stop the stream at the first all-zero header instead of erroring, when partial data is acceptable
- Fix the producer to publish the committed offset alongside the data
Defensive patterns
Strategy: validation
Validate before calling
// On the producer side: stream only up to the committed length, not the file size let committed_len = segment_metadata.size_in_bytes + segment::Header::LEN as u64; let mut limited = (&mut file).take(committed_len); // never read preallocated zero tail stream_from(&mut limited).await;
Type guard
fn is_all_zero_header(err: &io::Error) -> bool {
err.kind() == io::ErrorKind::InvalidData && err.to_string().contains("all-zeroes commit header")
} Try / catch
match writer.append_all(&mut stream, &mut progress).await {
Ok(done) => Ok(done),
Err(e) if is_all_zero_header(&e) => {
// tail of preallocated/torn data reached: treat stream as ended, keep what was written
Ok(StreamDone::Exhausted)
}
Err(e) => Err(e),
} Prevention
- Publish the committed offset with the stream; bound reads to it
- Trim trailing invalid data on the source before mirroring (OnTrailingData)
- Never stream a live segment to its fallocated length
When it happens
Trigger: The producer streamed a live segment up to its fallocated length instead of its committed length; the source crashed mid-write and the tail zeroes were included; zero padding was deliberately inserted into the stream.
Common situations: Mirroring by reading a segment file to file-size rather than to the last valid commit; snapshotting a file while it is being appended to; tail of a preallocated segment included by an off-by-length error.
Related errors
- no current segment, expected segment header
- expected commit offset
- failed to decode commit
- failed to read bytes of commit payload
- failed to read checksum
AI-assisted analysis of clockworklabs/SpacetimeDB@9e0d92412f (2026-08-20).
Data as JSON: /api/errors/efa7176311309045.
Report an issue: GitHub.
Appendix: source
Thrown at crates/commitlog/src/stream/writer.rs:306
// The stream is exhausted, break the outer loop.
trace!("eof");
return Ok(AppendInnerResult::StreamExhausted);
};
if buf.starts_with(&segment::MAGIC) {
// New segment, break inner loop.
trace!("segment marker");
return Ok(AppendInnerResult::SegmentMarker);
}
// Read the header, so we can determine the size of the commit.
if read_exact(stream, &mut self.commit_buf.header).await?.is_eof() {
return Ok(AppendInnerResult::StreamExhausted);
}
let Some(commit_header) = commit::Header::decode(&self.commit_buf.header[..])
.inspect_err(|e| warn!("failed to decode commit header: {e}"))?
else {
// Nb. eof handled above.
return Err(io::Error::new(io::ErrorKind::InvalidData, "all-zeroes commit header"));
};
// Read the rest of the commit.
self.commit_buf.body.resize(
commit_header.len as usize + CHECKSUM_LEN[current_segment.header.checksum_algorithm as usize],
0,
);
stream.read_exact(&mut self.commit_buf.body).await?;
// Decode the commit and verify its checksum.
let commit = StoredCommit::decode(&mut self.commit_buf.as_reader(bytes_written))
.inspect_err(|e| warn!("failed to decode commit: {e}"))?
.expect("commit decode cannot return `None` because we already decoded the header");
// Check that the commit offset is what we expect.
let expected_offset = self
.last_written_tx_range
.as_ref()
.map(|range| range.end)View on GitHub (pinned to 9e0d92412f)