{"record":{"id":"d356b904d6b20baa","repo":"rustfs/rustfs","slug":"data-block-count-exceeds-available-shards","errorCode":null,"errorMessage":"data block count exceeds available shards","messagePattern":"data block count exceeds available shards","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/ecstore/src/erasure/coding/decode.rs","lineNumber":1410,"sourceCode":"    en_blocks: &[Option<Vec<u8>>],\n    data_blocks: usize,\n    mut offset: usize,\n    length: usize,\n) -> std::io::Result<usize>\nwhere\n    W: tokio::io::AsyncWrite + Send + Sync + Unpin,\n{\n    if en_blocks.len() < data_blocks {\n        let reason = GetObjectFailureReason::RangeOrLengthInvalid;\n        record_get_object_pipeline_failure(GET_STAGE_RANGE, reason);\n        error!(\n            data_blocks,\n            available_shards = en_blocks.len(),\n            stage = GET_STAGE_RANGE,\n            reason = reason.as_str(),\n            \"Write data blocks received fewer shards than data blocks\"\n        );\n        return Err(io::Error::new(ErrorKind::InvalidInput, \"data block count exceeds available shards\"));\n    }\n\n    if length == 0 {\n        return Ok(0);\n    }\n\n    let Some(required_len) = offset.checked_add(length) else {\n        let reason = GetObjectFailureReason::RangeOrLengthInvalid;\n        record_get_object_pipeline_failure(GET_STAGE_RANGE, reason);\n        error!(\n            offset,\n            length,\n            stage = GET_STAGE_RANGE,\n            reason = reason.as_str(),\n            \"Write data blocks offset and length overflow\"\n        );\n        return Err(io::Error::new(ErrorKind::InvalidInput, \"offset + length overflows\"));\n    };","sourceCodeStart":1392,"sourceCodeEnd":1428,"githubUrl":"https://github.com/rustfs/rustfs/blob/9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de/crates/ecstore/src/erasure/coding/decode.rs#L1392-L1428","documentation":"Write-stage guard in write_data_blocks: the stripe's decoded/verified block vector (en_blocks) has fewer entries than the erasure code's data_blocks, so the requested object range cannot be emitted and the GET fails as InvalidInput at the range stage (RangeOrLengthInvalid reason). In practice the caller's Erasure metadata and the assembled block set disagree — corrupt or mismatched object metadata, or an internal pipeline invariant break.","triggerScenarios":"xl.meta ErasureInfo with data_shards larger than the number of blocks the decode pipeline assembled; objects read cross-pool after EC settings changed; truncated xl.meta after a crash; a caller passing a short block vector.","commonSituations":"Corrupt xl.meta on some shards; mixed-version clusters mid-upgrade; heal writing inconsistent metadata; custom callers of Erasure::decode with mismatched inputs.","solutions":["Dump the object's xl.meta (cargo run -p rustfs-filemeta --example dump_fileinfo) and compare data_shards across shards","Heal the object or re-upload it so metadata is rewritten consistently","If it reproduces on new objects, verify callers pass a block set built from the same ErasureInfo as the Erasure instance","Confirm pool/set EC configuration has not changed underneath existing objects"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Caller-side pre-check mirroring the guard\nif en_blocks.len() < data_blocks {\n    return Err(io::Error::new(\n        io::ErrorKind::InvalidInput,\n        format!(\"expected at least {} blocks, got {}\", data_blocks, en_blocks.len()),\n    ));\n}","typeGuard":null,"tryCatchPattern":"match erasure.decode(...).await {\n    (n, Some(e)) if e.kind() == std::io::ErrorKind::InvalidInput\n        && e.to_string().contains(\"data block count\") =>\n    {\n        // metadata/assembly mismatch: heal or re-upload; retrying unchanged will fail again\n    }\n    other => other,\n}","preventionTips":["Validate that xl.meta ErasureInfo matches the pool layout before reading","Run periodic heal so inconsistent metadata is repaired early","In custom callers, assert block-set size equals data_blocks before the write stage"],"tags":["erasure-coding","decode","metadata-mismatch","get","validation"],"backgroundTag":"erasure-metadata-mismatch","analyzedSha":"9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de","analyzedAt":"2026-08-16T20:34:17.560Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}