apache/hadoop · error · IOException
Commit block with mismatching GS. NN has {block}, client sub
Error message
Commit block with mismatching GS. NN has {block}, client submits {commitBlock} What it means
Thrown by NameNode BlockManager.commitBlock when a client finalizes the last block of a file but the generation stamp (GS) in the client's commit request does not match the GS the NameNode has recorded for that block. The NameNode tracks every block write/lease-recovery by bumping the block's generation stamp; a mismatch means the client is committing a different block instance than the one the NameNode believes is under construction. This usually indicates that lease recovery or another writer bumped the GS after this client started writing.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java:1192
/**
* Commit a block of a file
*
* @param block block to be committed
* @param commitBlock - contains client reported block length and generation
* @return true if the block is changed to committed state.
* @throws IOException if the block does not have at least a minimal number
* of replicas reported from data-nodes.
*/
private boolean commitBlock(final BlockInfo block,
final Block commitBlock) throws IOException {
if (block.getBlockUCState() == BlockUCState.COMMITTED)
return false;
assert block.getNumBytes() <= commitBlock.getNumBytes() :
"commitBlock length is less than the stored one "
+ commitBlock.getNumBytes() + " vs. " + block.getNumBytes();
if(block.getGenerationStamp() != commitBlock.getGenerationStamp()) {
throw new IOException("Commit block with mismatching GS. NN has " +
block + ", client submits " + commitBlock);
}
List<ReplicaUnderConstruction> staleReplicas =
block.commitBlock(commitBlock);
removeStaleReplicas(staleReplicas, block);
return true;
}
/**
* Commit the last block of the file and mark it as complete if it has
* meets the minimum redundancy requirement
*
* @param bc block collection
* @param commitBlock - contains client reported block length and generation
* @param iip - INodes in path to bc
* @return true if the last block is changed to committed state.
* @throws IOException if the block does not have at least a minimal number
* of replicas reported from data-nodes.View on GitHub (pinned to 2add963021)
Solutions
- Close/reopen the file: let the failed writer abort and have one client re-acquire the lease and continue with the block state the NN reports (recoverFileLease then append)
- Call ClientProtocol.recoverLease on the file before writing/appending so your client works with the post-recovery generation stamp
- Ensure only one client holds the write lease at a time (check LeaseManager via fsck/`hdfs dfsadmin` output or NN logs for concurrent lease recovery)
- Upgrade mismatched HDFS client/hadoop-distcp versions involved in the write so recovery handshake is consistent
Example fix
// before: retry completeFile with stale block GS after lease was recovered
fs.complete(file, newBlock); // newBlock GS != NN GS -> IOException mismatching GS
// after: recover lease first, then append/complete with NN's block state
if (!fs.append(file).hasNullBlock()) { /* re-acquire */ }
ClientProtocol cp = ((DistributedFileSystem) fs).getClient().getNamenode();
cp.recoverLease(file.toString(), clientName);
// re-fetch file status, re-open for append, write, then complete Defensive patterns
Strategy: retry
Validate before calling
// Before completing: recover the lease so client and NN agree on the last block's GS ClientProtocol nn = ((DistributedFileSystem) fs).getClient().getNamenode(); nn.recoverLease(src, clientName); // returns true when file is closed or client owns lease HdfsDataInputStream in = (HdfsDataInputStream) fs.open(src); LocatedBlock lb = in.getCurrentBlockLen() >= 0 ? in.readLocatedBlockInfo()[0] : null; // use lb's block id + GS from NN when issuing complete
Try / catch
try {
boolean closed = nn.complete(src, clientName, lastBlockFromNN, iip);
} catch (IOException e) {
if (e.getMessage().contains("mismatching GS")) {
nn.recoverLease(src, clientName); // adopt NN block state, then re-append and complete
} else { throw e; }
} Prevention
- Hold the write lease for the whole write; avoid concurrent writers on one file
- Call hflush/hsync periodically so client and NN block state stay aligned
- On any write failure, run recoverLease before re-opening for append
- Keep HDFS client version aligned with the cluster version
When it happens
Trigger: Client calls FSNamespaceOp/ClientProtocol.completeFile (or addBlock during retry) with a commitBlock whose getGenerationStamp() differs from block.getGenerationStamp() held by the NN; typically after lease recovery, block recovery by another client/DN, or a client retrying a write against stale block state. Also occurs when a client recovers a file (truncate/append path) and the recovered GS is not used in the subsequent commit.
Common situations: Two clients writing the same file (soft lease expired and lease taken over); a long-running writer paused (GC pause, network partition) while its lease was recovered; HDFS client version mismatch in recovery protocols; appends after a crash where recovered GS was not picked up.
Related errors
- Commit or complete block {commitBlock}, whereas it is under
- Cannot complete block: block has not been COMMITTED by the c
- Out of V1 (legacy) generation stamps
- Trying to commit inconsistent block: id = {blockId}, expecte
- Cannot complete block: block does not satisfy minimal replic
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/f44859848d724b34.
Report an issue: GitHub.