apache/hadoop · error · ReplicaAlreadyExistsException

r.getState() != ReplicaState.TEMPORARY, r={r}

Error message

r.getState() != ReplicaState.TEMPORARY, r={r}

What it means

convertTemporaryToRbw only makes sense for TEMPORARY replicas. If the volumeMap entry for the block exists but is in another state (RBW, FINALIZED, RWR), ReplicaAlreadyExistsException is thrown with the offending state: the requested conversion cannot proceed because the replica has already moved on.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java:1824

        b.getBlockPoolId(), getStorageUuidForLock(b),
        datasetSubLockStrategy.blockIdToSubLock(b.getBlockId()))) {
      final long blockId = b.getBlockId();
      final long expectedGs = b.getGenerationStamp();
      final long visible = b.getNumBytes();
      LOG.info("Convert " + b + " from Temporary to RBW, visible length="
          + visible);

      final ReplicaInfo temp;
      {
        // get replica
        final ReplicaInfo r = volumeMap.get(b.getBlockPoolId(), blockId);
        if (r == null) {
          throw new ReplicaNotFoundException(
              ReplicaNotFoundException.NON_EXISTENT_REPLICA + b);
        }
        // check the replica's state
        if (r.getState() != ReplicaState.TEMPORARY) {
          throw new ReplicaAlreadyExistsException(
              "r.getState() != ReplicaState.TEMPORARY, r=" + r);
        }
        temp = r;
      }
      // check generation stamp
      if (temp.getGenerationStamp() != expectedGs) {
        throw new ReplicaAlreadyExistsException(
            "temp.getGenerationStamp() != expectedGs = " + expectedGs
                + ", temp=" + temp);
      }

      // TODO: check writer?
      // set writer to the current thread
      // temp.setWriter(Thread.currentThread());

      // check length
      final long numBytes = temp.getNumBytes();
      if (numBytes < visible) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Refresh block locations and rebuild the pipeline - the state change usually means the work is already done
  2. Retry once after a pause when caused by racing operations
  3. Run 'hdfs fsck' on the block to verify its final state is consistent
  4. If it persists on one DN, trace that replica's state transitions in DN logs; invalidate it if wedged
Defensive patterns

Strategy: validation

Validate before calling

Replica r = fsDataset.getReplica(b.getBlockPoolId(), b.getBlockId());
if (r != null && r.getState() != ReplicaState.TEMPORARY) {
  // replica already moved on (finalized/RBW): rebuild from fresh locations
  refreshLocatedBlocksAndRebuildPipeline();
  return;
}
fsDataset.convertTemporaryToRbw(b, visible);

Type guard

boolean isTemporary(Replica r) {
  return r != null && r.getState() == ReplicaState.TEMPORARY;
}

Try / catch

catch (ReplicaAlreadyExistsException e) {
  if (e.getMessage() != null && e.getMessage().contains("TEMPORARY")) {
    refreshLocatedBlocksAndRebuildPipeline(); // work usually already done
  } else { throw e; }
}

Prevention

When it happens

Trigger: Pipeline setup expecting a temporary replica while the local replica is in a different state - finalized by a concurrent operation, or already converted to RBW by a racing pipeline setup.

Common situations: Racing recoveries/pipeline builds hitting the same block; stale located blocks implying a temp replica that has since been finalized; concurrent re-replication converting the replica underneath.

Related errors


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