apache/hadoop · error · IOException

Trying to remove a block from file {} which is not under con

Error message

Trying to remove a block from file {} which is not under construction.

What it means

In updateBlocks, a new block list shorter than the current one means a block abandon, which is only legal for a file under construction (abandonBlock on a file being written). If the file is already complete, the namespace state and the op disagree and replay throws IOException('Trying to remove a block from file <path> which is not under construction.').

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSEditLogLoader.java:1178

          setGenerationStampIfGreater(newGenerationStamp);

      if (!oldBlock.isComplete() &&
          (!isLastBlock || op.shouldCompleteLastBlock())) {
        changeMade = true;
        fsNamesys.getBlockManager().forceCompleteBlock(oldBlock);
      }
      if (changeMade) {
        // The state or gen-stamp of the block has changed. So, we may be
        // able to process some messages from datanodes that we previously
        // were unable to process.
        fsNamesys.getBlockManager().processQueuedMessagesForBlock(newBlock);
      }
    }
    
    if (newBlocks.length < oldBlocks.length) {
      // We're removing a block from the file, e.g. abandonBlock(...)
      if (!file.isUnderConstruction()) {
        throw new IOException("Trying to remove a block from file " +
            path + " which is not under construction.");
      }
      if (newBlocks.length != oldBlocks.length - 1) {
        throw new IOException("Trying to remove more than one block from file "
            + path);
      }
      Block oldBlock = oldBlocks[oldBlocks.length - 1];
      boolean removed = FSDirWriteFileOp.unprotectedRemoveBlock(
          fsDir, path, iip, file, oldBlock);
      if (!removed && !(op instanceof UpdateBlocksOp)) {
        throw new IOException("Trying to delete non-existant block " + oldBlock);
      }
    } else if (newBlocks.length > oldBlocks.length) {
      final boolean isStriped = ecPolicy != null;
      // We're adding blocks
      for (int i = oldBlocks.length; i < newBlocks.length; i++) {
        Block newBlock = newBlocks[i];
        final BlockInfo newBI;

View on GitHub (pinned to 2add963021)

Solutions

  1. Restore fsimage and edits from the same checkpoint epoch
  2. Run 'hdfs namenode -recover' to skip the inconsistent transaction
  3. Remove duplicated or overlapping segment files so the replay sequence is linear

Example fix

# before: edits replayed against a stale completed file
# IOException: Trying to remove a block from file /data/x which is not under construction.

# after: consistent restore
rm -rf /hadoop/dfs/name/current && cp -a backup/current /hadoop/dfs/name/current
Defensive patterns

Strategy: try-catch

Try / catch

try {
  loader.loadFSEdits(storage, 0);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().contains("which is not under construction")) {
    // a block removal replayed against a completed file: restore consistent
    // image+edits or run 'hdfs namenode -recover'
  }
  throw e;
}

Prevention

When it happens

Trigger: A block-removing list update replayed against a completed file: image and edits from different generations, duplicate replay of an update, or corrupted op data.

Common situations: Restored image already contains the file closed while later edits still abandon blocks; duplicated segments after manual recovery.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/423c91549d0a9821. Report an issue: GitHub.