{"record":{"id":"ce5a8d2033cca33a","repo":"rustfs/rustfs","slug":"invalid-erasure-coding-parameters","errorCode":null,"errorMessage":"Invalid erasure coding parameters","messagePattern":"Invalid erasure coding parameters","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/ecstore/src/erasure/coding/decode.rs","lineNumber":1725,"sourceCode":"        length: usize,\n        total_length: usize,\n        read_costs: Option<Vec<ShardReadCost>>,\n        deferred_handles: Vec<Option<DeferredReaderStripeHandle>>,\n    ) -> (usize, Option<std::io::Error>)\n    where\n        W: AsyncWrite + Send + Sync + Unpin,\n        R: crate::erasure::coding::ShardSource,\n    {\n        if readers.len() != self.data_shards + self.parity_shards {\n            record_get_object_pipeline_failure(GET_STAGE_RANGE, GetObjectFailureReason::RangeOrLengthInvalid);\n            return (0, Some(io::Error::new(ErrorKind::InvalidInput, \"Invalid number of readers\")));\n        }\n\n        // block_size/data_shards come from on-disk metadata; a corrupt FileInfo with a\n        // zero here must surface as an error, not a divide-by-zero panic on every GET.\n        if self.block_size == 0 || self.data_shards == 0 {\n            record_get_object_pipeline_failure(GET_STAGE_RANGE, GetObjectFailureReason::RangeOrLengthInvalid);\n            return (0, Some(io::Error::new(ErrorKind::InvalidInput, \"Invalid erasure coding parameters\")));\n        }\n\n        let Some(end_offset) = offset.checked_add(length) else {\n            record_get_object_pipeline_failure(GET_STAGE_RANGE, GetObjectFailureReason::RangeOrLengthInvalid);\n            return (0, Some(io::Error::new(ErrorKind::InvalidInput, \"offset + length exceeds total length\")));\n        };\n        if end_offset > total_length {\n            record_get_object_pipeline_failure(GET_STAGE_RANGE, GetObjectFailureReason::RangeOrLengthInvalid);\n            return (0, Some(io::Error::new(ErrorKind::InvalidInput, \"offset + length exceeds total length\")));\n        }\n\n        let mut ret_err = None;\n\n        if length == 0 {\n            return (0, ret_err);\n        }\n\n        let mut written = 0;","sourceCodeStart":1707,"sourceCodeEnd":1743,"githubUrl":"https://github.com/rustfs/rustfs/blob/9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de/crates/ecstore/src/erasure/coding/decode.rs#L1707-L1743","documentation":"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.","triggerScenarios":"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.","commonSituations":"Power loss during a metadata write; bit flips on failing drives; restoring data dirs onto a differently-configured pool.","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"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Pre-read metadata validation\nlet fi = FileInfo::load(...)?;\nif fi.erasure.block_size == 0 || fi.erasure.data_shards == 0 {\n    return Err(corrupted_object(&path));\n}","typeGuard":"fn is_zero_erasure_param(err: &std::io::Error) -> bool {\n    err.kind() == std::io::ErrorKind::InvalidInput\n        && err.to_string().contains(\"Invalid erasure coding parameters\")\n}","tryCatchPattern":"match get_object(...).await {\n    Err(e) if is_zero_erasure_param(&e) => {\n        // deterministic corruption: no retry; heal or restore from replica/tier\n        heal_or_restore(&path).await\n    }\n    r => r,\n}","preventionTips":["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"],"tags":["erasure-coding","corrupt-metadata","validation","decode","xl-meta"],"backgroundTag":"corrupt-object-metadata","analyzedSha":"9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de","analyzedAt":"2026-08-16T20:34:17.560Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}