{"record":{"id":"d1012344ae2f251c","repo":"apache/hadoop","slug":"missing-a-valid-replica-to-recover-from","errorCode":null,"errorMessage":"Missing a valid replica to recover from","messagePattern":"Missing a valid replica to recover from","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/ReplicaBuilder.java","lineNumber":296,"sourceCode":"    if (null != fromReplica && fromReplica.getState() == ReplicaState.RWR) {\n      return new ReplicaWaitingToBeRecovered(\n          (ReplicaWaitingToBeRecovered) fromReplica);\n    } else if (null != fromReplica){\n      throw new IllegalArgumentException(\"Incompatible fromReplica \"\n          + \"state: \" + fromReplica.getState());\n    } else {\n      if (null != block) {\n        return new ReplicaWaitingToBeRecovered(block, volume, directoryUsed);\n      } else {\n        return new ReplicaWaitingToBeRecovered(blockId, length, genStamp,\n            volume, directoryUsed);\n      }\n    }\n  }\n\n  private LocalReplica buildRUR() throws IllegalArgumentException {\n    if (null == fromReplica) {\n      throw new IllegalArgumentException(\n          \"Missing a valid replica to recover from\");\n    }\n    if (null != writer || null != block) {\n      throw new IllegalArgumentException(\"Invalid state for \"\n          + \"recovering from replica with blk id \"\n          + fromReplica.getBlockId());\n    }\n    if (fromReplica.getState() == ReplicaState.RUR) {\n      return new ReplicaUnderRecovery((ReplicaUnderRecovery) fromReplica);\n    } else {\n      return new ReplicaUnderRecovery(fromReplica, recoveryId);\n    }\n  }\n\n  private ProvidedReplica buildProvidedFinalizedReplica()\n      throws IllegalArgumentException {\n    ProvidedReplica info = null;\n    if (fromReplica != null) {","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/ReplicaBuilder.java#L278-L314","documentation":"ReplicaBuilder.buildRUR() creates a ReplicaUnderRecovery - a wrapper that tracks an existing replica through the recovery handshake. Unlike other build paths it has no from-scratch fallback: it requires from(replica), and a null source throws IllegalArgumentException 'Missing a valid replica to recover from'.","triggerScenarios":"new ReplicaBuilder(ReplicaState.RUR).setRecoveryId(id).build() (or a direct buildRUR call) without .from(existingReplica) - recovery was initiated without identifying which replica is being recovered.","commonSituations":"Block-recovery code paths or tests that build RUR replicas from IDs/fields only; races where the source replica was removed (invalidated) from the volume map before recovery was set up, leaving null to feed the builder.","solutions":["Always call .from(replica) with the live replica being recovered before building RUR.","Re-fetch the replica from ReplicaMap/FsVolumeReference right before .from() and fail the recovery cleanly if absent.","If the replica vanished (invalidated concurrently), abort recovery for that block instead of constructing RUR.","Add a null-check precondition with block context in your wrapper."],"exampleFix":"// before\nReplicaUnderRecovery rur = (ReplicaUnderRecovery) new ReplicaBuilder(ReplicaState.RUR)\n    .setRecoveryId(recoveryId).build();\n\n// after\nPreconditions.checkNotNull(source,\n    \"cannot recover block %s: replica not found\", blockId);\nReplicaUnderRecovery rur = (ReplicaUnderRecovery) new ReplicaBuilder(ReplicaState.RUR)\n    .from(source)\n    .setRecoveryId(recoveryId).build();","handlingStrategy":"validation","validationCode":"Preconditions.checkNotNull(source,\n    \"cannot recover block %s: replica not found\", blockId);\nReplicaUnderRecovery rur = (ReplicaUnderRecovery) new ReplicaBuilder(ReplicaState.RUR)\n    .from(source)\n    .setRecoveryId(recoveryId).build();","typeGuard":null,"tryCatchPattern":"try {\n  rur = (ReplicaUnderRecovery) builder.build();\n} catch (IllegalArgumentException e) {\n  throw new IOException(\"RUR setup failed for block \" + blockId + \": \"\n      + e.getMessage(), e);\n}","preventionTips":["RUR always requires from(replica); make it the first call in the chain.","Handle 'replica vanished' (concurrent invalidation) before entering recovery.","Wrap recovery setup so a missing source aborts that block's recovery cleanly."],"tags":["hdfs","datanode","replica","builder","block-recovery","required-parameter"],"backgroundTag":"missing-builder-parameter","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}