apache/hadoop · warning · ReplicaAlreadyExistsException
Replica {replicaInfo} already exists on storage {targetStora
Error message
Replica {replicaInfo} already exists on storage {targetStorageType} What it means
Thrown as ReplicaAlreadyExistsException from FsDatasetImpl.moveBlockAcrossStorage when replicaInfo.getVolume().getStorageType() already equals targetStorageType. The move request is a no-op: the replica lives on the requested storage tier already. It is a distinct exception type so callers (mover/NameNode block scheduler) can treat 'already satisfied' differently from real failures.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java:1097
* @return Returns the Old replicaInfo
* @throws IOException
*/
@Override
public ReplicaInfo moveBlockAcrossStorage(ExtendedBlock block,
StorageType targetStorageType, String targetStorageId)
throws IOException {
ReplicaInfo replicaInfo = getReplicaInfo(block);
if (replicaInfo.getState() != ReplicaState.FINALIZED) {
throw new ReplicaNotFoundException(
ReplicaNotFoundException.UNFINALIZED_REPLICA + block);
}
if (replicaInfo.getNumBytes() != block.getNumBytes()) {
throw new IOException("Corrupted replica " + replicaInfo
+ " with a length of " + replicaInfo.getNumBytes()
+ " expected length is " + block.getNumBytes());
}
if (replicaInfo.getVolume().getStorageType() == targetStorageType) {
throw new ReplicaAlreadyExistsException("Replica " + replicaInfo
+ " already exists on storage " + targetStorageType);
}
if (replicaInfo.isOnTransientStorage()) {
// Block movement from RAM_DISK will be done by LazyPersist mechanism
throw new IOException("Replica " + replicaInfo
+ " cannot be moved from storageType : "
+ replicaInfo.getVolume().getStorageType());
}
FsVolumeReference volumeRef = null;
boolean shouldConsiderSameMountVolume =
shouldConsiderSameMountVolume(replicaInfo.getVolume(),
targetStorageType, targetStorageId);
boolean useVolumeOnSameMount = false;
try (AutoCloseableLock lock = lockManager.readLock(LockLevel.BLOCK_POOl,
block.getBlockPoolId())) {View on GitHub (pinned to 2add963021)
Solutions
- Treat as success/no-op: catch ReplicaAlreadyExistsException in the caller and skip — do not count it as a move failure.
- Ensure only one mover runs per cluster/path at a time (Mover CLI coordination).
- Verify the block's actual placement with hdfs fsck -blocks -locations — if it already matches policy, the move queue is stale.
- No remediation on the replica itself is needed; nothing is wrong with the data.
Example fix
// before: treating every exception from move as fatal
try {
dataset.moveBlockAcrossStorage(block, StorageType.SSD, null);
} catch (IOException e) {
LOG.error("move failed", e);
}
// after: no-op case handled explicitly
try {
dataset.moveBlockAcrossStorage(block, StorageType.SSD, null);
} catch (ReplicaAlreadyExistsException e) {
LOG.debug("Replica already on target storage type: {}", block);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Skip the call entirely when the replica is already on target tier.
ReplicaInfo info = fsDataset.getReplica(
block.getBlockPoolId(), block.getBlockId());
if (info != null
&& info.getVolume().getStorageType() == targetStorageType) {
return info; // no-op: already satisfied
} Try / catch
// ReplicaAlreadyExistsException is the explicit no-op signal: absorb it.
try {
fsDataset.moveBlockAcrossStorage(block, StorageType.DISK, null);
} catch (ReplicaAlreadyExistsException e) {
LOG.debug("{} already on {}; nothing to do", block, StorageType.DISK);
return; // success-equivalent
} Prevention
- Compare current vs target storage type before issuing moves (idempotency guard).
- Catch ReplicaAlreadyExistsException separately from IOException and treat it as success.
- Run one mover per cluster path; duplicate movers generate most of these no-op exceptions.
When it happens
Trigger: Calling FsDatasetSpi.moveBlockAcrossStorage with a target type equal to the replica's current volume type — e.g. mover scheduling the same block twice, or a policy transition where the replica was already migrated by an earlier pass (or was written on the right tier to begin with).
Common situations: Concurrent mover instances; NameNode re-issuing satisfied moves after a DN re-registration; policy changed back and forth (HOT→COLD→HOT); duplicate scheduling during block-scheduler iterations.
Related errors
- Cannot append to an unfinalized replica {block}
- Failed to move meta file for {b} from {metadataURI} to {dstm
- Failed to move block file for {b} from {blockURI} to {absolu
- Corrupted replica {replicaInfo} with a length of {numBytes}
- Replica {replicaInfo} cannot be moved from storageType : {st
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/333e4c0727846ffe.
Report an issue: GitHub.