{"record":{"id":"8d10955bfa0a5065","repo":"rustfs/rustfs","slug":"missing-data-block","errorCode":null,"errorMessage":"Missing data block","messagePattern":"Missing data block","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/ecstore/src/erasure/coding/decode.rs","lineNumber":1461,"sourceCode":"        return Err(io::Error::new(ErrorKind::UnexpectedEof, \"Not enough data blocks to write\"));\n    }\n\n    let mut total_written = 0;\n    let mut write_left = length;\n\n    for block_op in &en_blocks[..data_blocks] {\n        let Some(block) = block_op else {\n            let reason = GetObjectFailureReason::ShortRead;\n            error!(\n                data_blocks,\n                offset,\n                length,\n                stage = GET_STAGE_EMIT,\n                reason = reason.as_str(),\n                \"Write data blocks found a missing data shard\"\n            );\n            record_get_object_pipeline_failure(GET_STAGE_EMIT, reason);\n            return Err(io::Error::new(ErrorKind::UnexpectedEof, \"Missing data block\"));\n        };\n\n        if offset >= block.len() {\n            offset -= block.len();\n            continue;\n        }\n\n        let block_slice = &block[offset..];\n        offset = 0;\n\n        let write_len = write_left.min(block_slice.len());\n        let write_stage_start = get_stage_timer_if_enabled(rustfs_io_metrics::get_stage_metrics_enabled());\n        if let Err(e) = writer.write_all(&block_slice[..write_len]).await {\n            if let Some(write_stage_start) = write_stage_start {\n                rustfs_io_metrics::record_get_object_duplex_backpressure_duration(write_stage_start.elapsed().as_secs_f64());\n            }\n            let reason = classify_io_error(&e);\n            if reason == GetObjectFailureReason::DownstreamClosed {","sourceCodeStart":1443,"sourceCodeEnd":1479,"githubUrl":"https://github.com/rustfs/rustfs/blob/9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de/crates/ecstore/src/erasure/coding/decode.rs#L1443-L1479","documentation":"Emit-stage guard in write_data_blocks: within the first data_blocks slots of the decoded stripe, at least one block is None. The up-front count check passed, but a required data block is missing — reconstruction should have filled every data slot before the write stage, so reaching this guard means stripe assembly and the write stage disagree. Fails with UnexpectedEof (ShortRead reason).","triggerScenarios":"Shard loss beyond what the stripe's reconstruction could fill while the write stage was still invoked; corrupted block bookkeeping between decode and write; a defect in the parallel reader's completion tracking.","commonSituations":"Degraded pools with more offline shards than expected; races between shard reads and reader retirement; version skew inside the decode pipeline.","solutions":["Check how many shards were readable for the object (offline drives) and heal the set","Capture the parallel reader's per-shard outcomes for the failing GET from metrics/debug logs; if quorum logic allowed a short set through, report it","Retry the GET after bringing the drives back online","If it reproduces with all shards healthy, preserve the object and open an issue with the stripe logs"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"fn is_missing_block(err: &std::io::Error) -> bool {\n    err.kind() == std::io::ErrorKind::UnexpectedEof\n        && err.to_string().contains(\"Missing data block\")\n}","tryCatchPattern":"match result {\n    Err(e) if is_missing_block(&e) => {\n        // stripe assembly inconsistent: retry once after refresh; then heal/fallback\n    }\n    r => r,\n}","preventionTips":["Keep enough drives online that decode quorum never reaches the write stage short","Run heal after replacing drives","Preserve stripe logs when this fires — it indicates an internal inconsistency worth reporting"],"tags":["erasure-coding","missing-shard","unexpected-eof","decode","get"],"backgroundTag":"erasure-missing-shard","analyzedSha":"9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de","analyzedAt":"2026-08-16T20:34:17.560Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}