apache/hadoop · error · IllegalArgumentException
Missing a valid replica to recover from
Error message
Missing a valid replica to recover from
What it means
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'.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/ReplicaBuilder.java:296
if (null != fromReplica && fromReplica.getState() == ReplicaState.RWR) {
return new ReplicaWaitingToBeRecovered(
(ReplicaWaitingToBeRecovered) fromReplica);
} else if (null != fromReplica){
throw new IllegalArgumentException("Incompatible fromReplica "
+ "state: " + fromReplica.getState());
} else {
if (null != block) {
return new ReplicaWaitingToBeRecovered(block, volume, directoryUsed);
} else {
return new ReplicaWaitingToBeRecovered(blockId, length, genStamp,
volume, directoryUsed);
}
}
}
private LocalReplica buildRUR() throws IllegalArgumentException {
if (null == fromReplica) {
throw new IllegalArgumentException(
"Missing a valid replica to recover from");
}
if (null != writer || null != block) {
throw new IllegalArgumentException("Invalid state for "
+ "recovering from replica with blk id "
+ fromReplica.getBlockId());
}
if (fromReplica.getState() == ReplicaState.RUR) {
return new ReplicaUnderRecovery((ReplicaUnderRecovery) fromReplica);
} else {
return new ReplicaUnderRecovery(fromReplica, recoveryId);
}
}
private ProvidedReplica buildProvidedFinalizedReplica()
throws IllegalArgumentException {
ProvidedReplica info = null;
if (fromReplica != null) {View on GitHub (pinned to 2add963021)
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.
Example fix
// before
ReplicaUnderRecovery rur = (ReplicaUnderRecovery) new ReplicaBuilder(ReplicaState.RUR)
.setRecoveryId(recoveryId).build();
// after
Preconditions.checkNotNull(source,
"cannot recover block %s: replica not found", blockId);
ReplicaUnderRecovery rur = (ReplicaUnderRecovery) new ReplicaBuilder(ReplicaState.RUR)
.from(source)
.setRecoveryId(recoveryId).build(); Defensive patterns
Strategy: validation
Validate before calling
Preconditions.checkNotNull(source,
"cannot recover block %s: replica not found", blockId);
ReplicaUnderRecovery rur = (ReplicaUnderRecovery) new ReplicaBuilder(ReplicaState.RUR)
.from(source)
.setRecoveryId(recoveryId).build(); Try / catch
try {
rur = (ReplicaUnderRecovery) builder.build();
} catch (IllegalArgumentException e) {
throw new IOException("RUR setup failed for block " + blockId + ": "
+ e.getMessage(), e);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- A valid writer is required for constructing a RBW from block
- A valid writer is required for constructing a Replica from b
- Invalid state for recovering from replica with blk id {}
- Unknown replica state {}
- Incompatible fromReplica state: {}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/d1012344ae2f251c.
Report an issue: GitHub.