apache/hadoop · error · IOException
Update {} but the new block {} does not have a larger genera
Error message
Update {} but the new block {} does not have a larger generation stamp than the last block {} What it means
updateBlock enforces generation-stamp monotonicity: the replacement block's GS must be strictly greater than the last block's current GS. A smaller or equal GS means the caller is applying stale recovery metadata, so the update is rejected with an IOException after a warn log.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java:6201
private void updatePipelineInternal(String clientName, ExtendedBlock oldBlock,
ExtendedBlock newBlock, DatanodeID[] newNodes, String[] newStorageIDs,
boolean logRetryCache)
throws IOException {
assert hasWriteLock(RwLockMode.GLOBAL);
// check the vadility of the block and lease holder name
final INodeFile pendingFile = checkUCBlock(oldBlock, clientName);
final String src = pendingFile.getFullPathName();
final BlockInfo lastBlock = pendingFile.getLastBlock();
assert !lastBlock.isComplete();
// check new GS & length: this is not expected
if (newBlock.getGenerationStamp() <= lastBlock.getGenerationStamp()) {
final String msg = "Update " + oldBlock + " but the new block " + newBlock
+ " does not have a larger generation stamp than the last block "
+ lastBlock;
LOG.warn(msg);
throw new IOException(msg);
}
if (newBlock.getNumBytes() < lastBlock.getNumBytes()) {
final String msg = "Update " + oldBlock + " (size="
+ oldBlock.getNumBytes() + ") to a smaller size block " + newBlock
+ " (size=" + newBlock.getNumBytes() + ")";
LOG.warn(msg);
throw new IOException(msg);
}
// Update old block with the new generation stamp and new length
blockManager.updateLastBlock(lastBlock, newBlock);
// find the DatanodeDescriptor objects
final DatanodeStorageInfo[] storages = blockManager.getDatanodeManager()
.getDatanodeStorageInfos(newNodes, newStorageIDs,
"src=%s, oldBlock=%s, newBlock=%s, clientName=%s",
src, oldBlock, newBlock, clientName);
lastBlock.getUnderConstructionFeature().setExpectedLocations(lastBlock,View on GitHub (pinned to 2add963021)
Solutions
- Re-fetch the current last block (getBlockLocations / ExtendedBlock) and build the update from its latest GS
- Ensure one recovery driver per block at a time
- Treat the error as 'state moved on': verify final state instead of blind retry
Defensive patterns
Strategy: retry
Try / catch
try {
updateBlock(oldBlock, newBlock, ...);
} catch (IOException e) {
if (e.getMessage().contains("does not have a larger generation stamp")) {
LocatedBlock cur = dfs.getClient().getLastLocatedBlock(path);
ExtendedBlock fixed = new ExtendedBlock(cur.getBlock().getBlockPoolId(),
cur.getBlock().getBlockId(), newLen, cur.getBlock().getGenerationStamp() + 1);
updateBlock(cur.getBlock(), fixed, ...); // rebuild from current GS
} else { throw e; }
} Prevention
- Derive the new GS from the block's current GS, never from a cached value
- Single driver per block recovery to avoid concurrent GS bumps
When it happens
Trigger: Retrying updateBlock with a previously generated stamp after another recovery already advanced the block's GS; two concurrent recoveries computing updates off the same base state.
Common situations: Timeout-retry logic that reuses the old newBlock; races between a client and a lease-recovery thread updating the same last block.
Related errors
- Out of V1 (legacy) generation stamps
- Commit block with mismatching GS. NN has {block}, client sub
- Mismatched block IDs or generation stamps for the old last b
- Mismatched block IDs or generation stamps, attempting to rep
- Block (={}) not found
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/714e7f8cbb9736ea.
Report an issue: GitHub.