apache/hadoop · error · IOException
Unexpected BlockUCState: {} is {} but not UNDER_CONSTRUCTION
Error message
Unexpected BlockUCState: {} is {} but not UNDER_CONSTRUCTION What it means
checkUCBlock found the block but its BlockUCState is not UNDER_CONSTRUCTION (already COMMITTED or COMPLETE), so a new generation stamp cannot be minted for it. The block has moved past the recoverable state the caller assumes.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java:6041
file.getFileWithSnapshotFeature().isCurrentFileDeleted()) {
return true;
}
return false;
}
private INodeFile checkUCBlock(ExtendedBlock block,
String clientName) throws IOException {
assert hasWriteLock(RwLockMode.GLOBAL);
checkNameNodeSafeMode("Cannot get a new generation stamp and an "
+ "access token for block " + block);
// check stored block state
BlockInfo storedBlock = getStoredBlock(ExtendedBlock.getLocalBlock(block));
if (storedBlock == null) {
throw new IOException(block + " does not exist.");
}
if (storedBlock.getBlockUCState() != BlockUCState.UNDER_CONSTRUCTION) {
throw new IOException("Unexpected BlockUCState: " + block
+ " is " + storedBlock.getBlockUCState()
+ " but not " + BlockUCState.UNDER_CONSTRUCTION);
}
// check file inode
final INodeFile file = getBlockCollection(storedBlock);
if (file == null || !file.isUnderConstruction() || isFileDeleted(file)) {
throw new IOException("The file " + storedBlock +
" belonged to does not exist or it is not under construction.");
}
// check lease
if (clientName == null
|| !clientName.equals(file.getFileUnderConstructionFeature()
.getClientName())) {
throw new LeaseExpiredException("Lease mismatch: " + block +
" is accessed by a non lease holder " + clientName);
}View on GitHub (pinned to 2add963021)
Solutions
- Refresh block state (getBlockLocations) and if the file is closed, accept the earlier recovery as final
- If the file is still open, re-run recoverLease and continue from the new block state
- Serialize recovery attempts per file in client code
Defensive patterns
Strategy: retry
Validate before calling
LocatedBlock last = dfs.getClient().getLastLocatedBlock(path);
if (last != null && last.isBlockUnderConstruction()) { /* safe to request new GS */ } Try / catch
try {
nextGenerationStamp(block, clientName);
} catch (IOException e) {
if (e.getMessage().contains("Unexpected BlockUCState")) {
// state advanced (committed/completed): verify file state and move on
if (dfs.isFileClosed(path)) { return; }
dfs.recoverLease(path); // else restart recovery from current state
} else { throw e; }
} Prevention
- Check the block's UC state from LocatedBlock before requesting a new GS
- Never blindly retry recovery; first confirm what already happened
When it happens
Trigger: Pipeline recovery racing block commit or file completion: the block got committed by a first (unacknowledged) attempt, or lease recovery elsewhere advanced the block state.
Common situations: Timeout-and-retry of updateBlock without checking state; two clients concurrently recovering the same file.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot complete block: block has not been COMMITTED by the c
- Recovery block {b} where it is not under construction.
- DIR* NameSystem.internalReleaseLease: attempt to release a c
- Cannot finalize file {} because it is not under construction
- Block (={}) not found
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/3b6c90ac01c4145e.
Report an issue: GitHub.