apache/hadoop · warning · ReplicaNotFoundException
Cannot append to an unfinalized replica {block}
Error message
Cannot append to an unfinalized replica {block} What it means
Thrown as ReplicaNotFoundException (UNFINALIZED_REPLICA prefix, 'Cannot append to an unfinalized replica') from FsDatasetImpl.moveBlockAcrossStorage(ExtendedBlock, StorageType, String) when the resolved replica's state is not FINALIZED — i.e. it is RBW (being written), RWR (recovered write), TEMP, or RUR. Storage-type moves only apply to finalized replicas, because unfinalized files are still owned by an active writer.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java:1088
+ dstMeta, e);
}
LOG.debug("Linked {} to {} . Dest meta file: {}", srcReplicaUri, dstFile,
dstMeta);
return new File[]{dstMeta, dstFile};
}
/**
* Move block files from one storage to another storage.
* @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());
}View on GitHub (pinned to 2add963021)
Solutions
- Close/wait for writers of the file (lease expiry or app completion) and re-run the mover — finalized replicas move fine.
- Check replica state on the DN: the exception text includes the replica (toString carries state, e.g. RBW/RWR); confirm with the DN's block report for that block.
- If the replica is stuck RWR/RUR after a dead writer, recover the lease (hdfs debug recoverLease) to finalize it, then move.
- This is transient for the mover — it logs and retries later; no data is at risk.
Defensive patterns
Strategy: validation
Validate before calling
// Check replica state before requesting a cross-storage move.
ReplicaInfo info = fsDataset.getReplica(
block.getBlockPoolId(), block.getBlockId());
if (info == null || info.getState() != ReplicaState.FINALIZED) {
// skip this block; the mover will revisit once writes finish
continue;
} Try / catch
// Treat unfinalized as 'try later', matching mover semantics.
try {
fsDataset.moveBlockAcrossStorage(block, StorageType.ARCHIVE, null);
} catch (ReplicaNotFoundException e) {
if (e.getMessage().contains("unfinalized")) {
LOG.debug("Block {} not finalized yet; deferring move", block);
deferForNextPass(block);
} else {
throw e;
}
} Prevention
- Run mover against files that are closed (no active lease): hdfs fsck -openforwrite to find blockers.
- Skip replicas whose state is not FINALIZED before issuing move calls.
- Expect and tolerate these exceptions in mover loops — they are scheduling noise, not failures.
When it happens
Trigger: NameNode/mover requests a storage-policy move (setStoragePolicy + Mover, or fast move during block scheduling) for a block whose local replica is mid-write: an open file's block, a block under lease recovery, or a replica still in RBW after a pipeline failure.
Common situations: Mover run while a job is actively writing the file; setStoragePolicy applied to open files; HDFS-9913-era fast move racing a replication recovery; block scanner-triggered moves of recently recovered RWR replicas.
Related errors
- Replica {replicaInfo} already exists on storage {targetStora
- 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/5d4794471c004e03.
Report an issue: GitHub.