apache/hadoop · error · ReplicaAlreadyExistsException
temp.getGenerationStamp() != expectedGs = {expectedGs}, temp
Error message
temp.getGenerationStamp() != expectedGs = {expectedGs}, temp={temp} What it means
Before converting a TEMPORARY replica to RBW, FsDatasetImpl verifies the replica's generation stamp equals expectedGs taken from the ExtendedBlock. A mismatch (stale or advanced stamp) throws ReplicaAlreadyExistsException, preventing the pipeline from continuing against the wrong block incarnation.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java:1831
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) {
throw new IOException(numBytes + " = numBytes < visible = "
+ visible + ", temp=" + temp);
}
// check volume
final FsVolumeImpl v = (FsVolumeImpl) temp.getVolume();
if (v == null) {
throw new IOException("r.getVolume() = null, temp=" + temp);View on GitHub (pinned to 2add963021)
Solutions
- Refresh located blocks so the GSs match, then retry the conversion/pipeline
- Ensure only one recovery incarnation runs at a time for the block
- If the temp replica's GS is stale leftovers, invalidate it and let re-replication replace it
- Run 'hdfs fsck' to reconcile replica GSs across DNs
Defensive patterns
Strategy: validation
Validate before calling
Replica r = fsDataset.getReplica(b.getBlockPoolId(), b.getBlockId());
if (r != null && r.getGenerationStamp() != b.getGenerationStamp()) {
refetchLocatedBlockAndRebuildPipeline(); // GS moved on; do not convert this temp replica
return;
}
fsDataset.convertTemporaryToRbw(b, visible); Type guard
boolean gsMatches(Replica r, ExtendedBlock b) {
return r != null && r.getGenerationStamp() == b.getGenerationStamp();
} Try / catch
catch (ReplicaAlreadyExistsException e) {
if (e.getMessage() != null && e.getMessage().contains("expectedGs")) {
refetchLocatedBlockAndRetryOnce();
} else { throw e; }
} Prevention
- Never mix generation stamps across retries: pair the ExtendedBlock's GS with the exact replica being targeted
- Re-fetch located blocks after any lease-recovery event before opening pipelines
- Run only one recovery incarnation per block at a time
When it happens
Trigger: convertTemporaryToRbw where the temp replica's GS differs from the block's GS - typically a recovery bumped the GS after the temp replica was created, and the client is driving a pipeline with mismatched stamps.
Common situations: Lease/block recovery racing a replication transfer; stale located blocks carrying an old GS; a client retry mixing ExtendedBlocks from different block incarnations.
Related errors
- Replica does not exist {b}
- r.getState() != ReplicaState.TEMPORARY, r={r}
- {numBytes} = numBytes < visible = {visible}, temp={temp}
- Replica gen stamp < block genstamp, block={block}, replica={
- Failed to create temporary file for {}. File {} should not
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/1f226d47ee524d82.
Report an issue: GitHub.