risingwavelabs/risingwave · error · BackupError
unexpected EOF while decoding meta snapshot
Error message
unexpected EOF while decoding meta snapshot
What it means
BackupError::from(std::io::Error) maps an UnexpectedEof IO error to BackupError::Decoding with the message "unexpected EOF while decoding meta snapshot". It means the reader reached end-of-file while reading a metadata snapshot from backup storage, i.e. the snapshot file/stream is shorter than the decoder expected. The conversion exists so truncated snapshot reads surface as decoding errors rather than generic storage errors.
Solutions
- Re-upload or restore from a different, intact meta snapshot backup; verify the snapshot object's byte length matches expectations.
- Check that the backup was fully written (compare content_length/checksum recorded at creation time against the stored object).
- Verify you are decoding with the reader version matching the snapshot format version (V1 vs V2).
- If reproducible, capture the object store logs / read path (ObjectDataStreamReader) and file a bug with the backup manifest.
Example fix
// before: blindly decoding a snapshot path from env let snap = MetaSnapshotV2::decode_from_reader(reader).await?; // after: validate snapshot size/known-good backup first assert_snapshot_intact(&manifest, &storage)?; // compares length + checksum let snap = MetaSnapshotV2::decode_from_reader(reader).await?;
Defensive patterns
Strategy: validation
Validate before calling
let size = storage.get_object_size(&snapshot_key).await?;
if size < MIN_SNAPSHOT_SIZE { return Err(anyhow!("snapshot {} truncated ({} bytes)", snapshot_key, size)); }
// optionally verify recorded checksum before decoding
verify_manifest_checksum(&manifest, &storage, &snapshot_key).await?; Type guard
fn is_snapshot_intact(manifest: &BackupManifest, actual_size: u64) -> bool {
actual_size == manifest.snapshot_size && actual_size >= 8
} Try / catch
match MetaSnapshotV2::decode_from_reader(reader).await {
Ok(snap) => snap,
Err(e) if e.to_string().contains("unexpected EOF") => {
return Err(anyhow!("snapshot corrupted/truncated; use another backup"));
}
Err(e) => return Err(e.into()),
} Prevention
- Record snapshot size and checksum in the backup manifest at creation time and verify before restore.
- Avoid interrupting backup uploads; use atomic/complete-then-commit object writes.
- Pin reader version to the snapshot format version produced by your cluster.
When it happens
Trigger: Reading a meta snapshot via MetaSnapshotV1/V2 readers (decode_from_reader, read_to_end, decode_hummock_sequences_from_stream, finish) when the underlying object storage reader returns UnexpectedEof mid-decode, e.g. the snapshot object was truncated, partially uploaded, or the object reader's expected size exceeds the actual stored bytes.
Common situations: A backup upload was interrupted so the stored snapshot object is truncated; the wrong (older) snapshot version is fetched with a newer reader expecting more data; object storage returns fewer bytes than the manifest claims; manual tampering or a corrupted backup file.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- meta snapshot is missing checksum
- metadata snapshot is truncated while reading u32
- prost payload length
- BackupStorage error
- Checksum mismatch: expected
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/dddd93818fff4ace.
Report an issue: GitHub.
Appendix: source
Thrown at src/storage/backup/src/error.rs:67
#[source]
BoxedError,
),
#[error("Checksum mismatch: expected {expected}, found: {found}")]
ChecksumMismatch { expected: u64, found: u64 },
#[error("Meta storage is not empty before being restored")]
NonemptyMetaStorage,
#[error(transparent)]
Other(
#[from]
#[backtrace]
anyhow::Error,
),
}
impl From<std::io::Error> for BackupError {
fn from(err: std::io::Error) -> Self {
if err.kind() == std::io::ErrorKind::UnexpectedEof {
Self::Decoding(anyhow::anyhow!("unexpected EOF while decoding meta snapshot").into())
} else {
Self::BackupStorage(err.into())
}
}
}
View on GitHub (pinned to 6469eb736d)