apache/hadoop · error · IOException
The blockCollection of {} is null, likely because the file o
Error message
The blockCollection of {} is null, likely because the file owning this block was deleted and the block removal is delayed What it means
storedBlock.isDeleted() is true: the block's blockCollection was nulled because the owning file was deleted and physical block removal is delayed for performance. commitBlockSynchronization throws IOException here instead of hitting an NPE, and avoids appending a CloseOp edit for a dead file (HDFS-6825).
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java:4106
throw new IOException("Block (=" + oldBlock + ") not found");
}
}
final long oldGenerationStamp = storedBlock.getGenerationStamp();
final long oldNumBytes = storedBlock.getNumBytes();
//
// The implementation of delete operation (see @deleteInternal method)
// first removes the file paths from namespace, and delays the removal
// of blocks to later time for better performance. When
// commitBlockSynchronization (this method) is called in between, the
// blockCollection of storedBlock could have been assigned to null by
// the delete operation, throw IOException here instead of NPE; if the
// file path is already removed from namespace by the delete operation,
// throw FileNotFoundException here, so not to proceed to the end of
// this method to add a CloseOp to the edit log for an already deleted
// file (See HDFS-6825).
//
if (storedBlock.isDeleted()) {
throw new IOException("The blockCollection of " + storedBlock
+ " is null, likely because the file owning this block was"
+ " deleted and the block removal is delayed");
}
final INodeFile iFile = getBlockCollection(storedBlock);
src = iFile.getFullPathName();
if (isFileDeleted(iFile)) {
throw new FileNotFoundException("File not found: "
+ src + ", likely due to delayed block removal");
}
if ((!iFile.isUnderConstruction() || storedBlock.isComplete()) &&
iFile.getLastBlock().isComplete()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Unexpected block (={}) since the file (={}) is not under construction",
oldBlock, iFile.getLocalName());
}
return;
}View on GitHub (pinned to 2add963021)
Solutions
- Treat the write as terminally failed: the file is gone, so no commit is needed
- If the file should still exist, verify with getFileStatus and re-run the client operation once block GC has settled
- Serialize application-level delete and finalize so they cannot interleave on the same path
Defensive patterns
Strategy: try-catch
Try / catch
try {
commitBlockSynchronization(oldBlock, newGs, newLen, ...);
} catch (IOException e) {
if (e.getMessage().contains("blockCollection") && !fs.exists(path)) {
return; // file deleted, delayed block removal: no-op
}
throw e;
} Prevention
- Do not delete files while recovery operations may still be in flight
- Treat delayed block removal windows as normal; re-check existence on failure
When it happens
Trigger: A delete removes the path from the namespace first and invalidates blocks later; commitBlockSynchronization arrives inside that window and finds a block whose owner is already detached.
Common situations: Users deleting output files at the exact moment a failed write is being recovered; cleanup jobs racing stragglers; committer aborting a task while its pipeline syncs.
Related errors
- Recovery block {b} where it is not under construction.
- File is deleted: {} (inode {}) {}
- File not found: {}, likely due to delayed block removal
- Directory does not exist: {}
- File does not exist: {}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/e02e9ec09545c9a2.
Report an issue: GitHub.