rustfs/rustfs · error · io::Error
Invalid erasure coding parameters
Error message
Invalid erasure coding parameters
What it means
Guard in Erasure::decode against on-disk metadata whose block_size or data_shards is zero — values that would otherwise cause a divide-by-zero panic on every GET. These fields come from xl.meta, so a zero means the FileInfo is corrupt or was written by an incompatible layout; decode surfaces it as InvalidInput at the range stage instead of panicking.
Source
Thrown at crates/ecstore/src/erasure/coding/decode.rs:1725
length: usize,
total_length: usize,
read_costs: Option<Vec<ShardReadCost>>,
deferred_handles: Vec<Option<DeferredReaderStripeHandle>>,
) -> (usize, Option<std::io::Error>)
where
W: AsyncWrite + Send + Sync + Unpin,
R: crate::erasure::coding::ShardSource,
{
if readers.len() != self.data_shards + self.parity_shards {
record_get_object_pipeline_failure(GET_STAGE_RANGE, GetObjectFailureReason::RangeOrLengthInvalid);
return (0, Some(io::Error::new(ErrorKind::InvalidInput, "Invalid number of readers")));
}
// block_size/data_shards come from on-disk metadata; a corrupt FileInfo with a
// zero here must surface as an error, not a divide-by-zero panic on every GET.
if self.block_size == 0 || self.data_shards == 0 {
record_get_object_pipeline_failure(GET_STAGE_RANGE, GetObjectFailureReason::RangeOrLengthInvalid);
return (0, Some(io::Error::new(ErrorKind::InvalidInput, "Invalid erasure coding parameters")));
}
let Some(end_offset) = offset.checked_add(length) else {
record_get_object_pipeline_failure(GET_STAGE_RANGE, GetObjectFailureReason::RangeOrLengthInvalid);
return (0, Some(io::Error::new(ErrorKind::InvalidInput, "offset + length exceeds total length")));
};
if end_offset > total_length {
record_get_object_pipeline_failure(GET_STAGE_RANGE, GetObjectFailureReason::RangeOrLengthInvalid);
return (0, Some(io::Error::new(ErrorKind::InvalidInput, "offset + length exceeds total length")));
}
let mut ret_err = None;
if length == 0 {
return (0, ret_err);
}
let mut written = 0;View on GitHub (pinned to 9e6e02ea09)
Solutions
- Dump the object's xl.meta and inspect ErasureInfo (block_size, data_shards)
- Heal the object so metadata is rebuilt from healthy shards, or restore from replication/tier
- If many objects show zeros, suspect the underlying disk (smartctl) and replace it
- Do not hand-edit xl.meta; use heal tooling to rewrite metadata
Defensive patterns
Strategy: fallback
Validate before calling
// Pre-read metadata validation
let fi = FileInfo::load(...)?;
if fi.erasure.block_size == 0 || fi.erasure.data_shards == 0 {
return Err(corrupted_object(&path));
} Type guard
fn is_zero_erasure_param(err: &std::io::Error) -> bool {
err.kind() == std::io::ErrorKind::InvalidInput
&& err.to_string().contains("Invalid erasure coding parameters")
} Try / catch
match get_object(...).await {
Err(e) if is_zero_erasure_param(&e) => {
// deterministic corruption: no retry; heal or restore from replica/tier
heal_or_restore(&path).await
}
r => r,
} Prevention
- Validate ErasureInfo (non-zero block_size/data_shards) when loading xl.meta
- Run periodic heal so corrupt metadata is rebuilt from healthy shards
- Use durable metadata writes (fsync) and healthy drives to avoid truncated xl.meta
When it happens
Trigger: Reading an object whose xl.meta carries block_size=0 or data_shards=0: truncated metadata after a crash, disk corruption, or data directories copied between clusters with different erasure settings.
Common situations: Power loss during a metadata write; bit flips on failing drives; restoring data dirs onto a differently-configured pool.
Related errors
- erasure reader requires data shards
- erasure reader requires non-zero block size
- data block count exceeds available shards
- Invalid number of readers
- missing shard {index} after RustFS codec reconstruction
AI-assisted analysis of rustfs/rustfs@9e6e02ea09 (2026-08-16).
Data as JSON: /api/errors/ce5a8d2033cca33a.
Report an issue: GitHub.