apache/hadoop · error · IllegalArgumentException

Invalid state for recovering from replica with blk id {}

Error message

Invalid state for recovering from replica with blk id {}

What it means

ReplicaBuilder.buildRUR() throws IllegalArgumentException 'Invalid state for recovering from replica' when the builder was configured with a writer thread (setWriterThread) or a Block (setBlock) in addition to from(replica). Recovery wraps an existing replica; writer/block are write-path inputs that contradict recovery semantics.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/ReplicaBuilder.java:300

      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) {
      throw new IllegalArgumentException("Finalized PROVIDED replica " +
          "cannot be constructed from another replica");
    }
    if (fileRegion == null && uri == null &&

View on GitHub (pinned to 2add963021)

Solutions

  1. For RUR, set only from(replica) and setRecoveryId(long); remove setWriterThread/setBlock from the chain.
  2. Split per-state builder factories so each state sets exactly its own inputs.
  3. Add a precondition in your wrapper: writer == null && block == null when building RUR.

Example fix

// before
ReplicaUnderRecovery rur = (ReplicaUnderRecovery) new ReplicaBuilder(ReplicaState.RUR)
    .setBlock(block)
    .setWriterThread(writer)
    .from(source)
    .setRecoveryId(recoveryId).build();

// after
ReplicaUnderRecovery rur = (ReplicaUnderRecovery) new ReplicaBuilder(ReplicaState.RUR)
    .from(source)
    .setRecoveryId(recoveryId).build();
Defensive patterns

Strategy: validation

Validate before calling

Preconditions.checkState(writer == null && block == null,
    "RUR construction accepts only from() + setRecoveryId()");
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 " + source.getBlockId()
      + ": " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: new ReplicaBuilder(ReplicaState.RUR).from(source).setWriterThread(t).build() or the same with .setBlock(block) - i.e. copy-pasted builder chains from RBW/TEMPORARY construction reused for the RUR path.

Common situations: Shared builder helper methods that 'set everything' (block, writer, recoveryId) regardless of target state; test fixtures that configure one generic builder and reuse it for multiple states including RUR.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/70e73e8801f2b380. Report an issue: GitHub.