{"record":{"id":"e28988c73cc96e57","repo":"apache/hadoop","slug":"file-is-not-under-construction","errorCode":null,"errorMessage":"File is not under construction: {}","messagePattern":"File is not under construction: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSEditLogLoader.java","lineNumber":507,"sourceCode":"\n      final INodesInPath iip = fsDir.getINodesInPath(path, DirOp.READ);\n      final INodeFile file = INodeFile.valueOf(iip.getLastINode(), path);\n\n      // Update the salient file attributes.\n      file.setAccessTime(addCloseOp.atime, Snapshot.CURRENT_STATE_ID, false);\n      file.setModificationTime(addCloseOp.mtime, Snapshot.CURRENT_STATE_ID);\n      ErasureCodingPolicy ecPolicy =\n          FSDirErasureCodingOp.unprotectedGetErasureCodingPolicy(\n              fsDir.getFSNamesystem(), iip);\n      updateBlocks(fsDir, addCloseOp, iip, file, ecPolicy);\n\n      // Now close the file\n      if (!file.isUnderConstruction() &&\n          logVersion <= LayoutVersion.BUGFIX_HDFS_2991_VERSION) {\n        // There was a bug (HDFS-2991) in hadoop < 0.23.1 where OP_CLOSE\n        // could show up twice in a row. But after that version, this\n        // should be fixed, so we should treat it as an error.\n        throw new IOException(\n            \"File is not under construction: \" + path);\n      }\n      // One might expect that you could use removeLease(holder, path) here,\n      // but OP_CLOSE doesn't serialize the holder. So, remove the inode.\n      if (file.isUnderConstruction()) {\n        fsNamesys.getLeaseManager().removeLease(file.getId());\n        file.toCompleteFile(file.getModificationTime(), 0,\n            fsNamesys.getBlockManager().getMinReplication());\n      }\n      break;\n    }\n    case OP_APPEND: {\n      AppendOp appendOp = (AppendOp) op;\n      final String path = renameReservedPathsOnUpgrade(appendOp.path,\n          logVersion);\n      if (FSNamesystem.LOG.isDebugEnabled()) {\n        FSNamesystem.LOG.debug(op.opCode + \": \" + path +\n            \" clientName \" + appendOp.clientName +","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSEditLogLoader.java#L489-L525","documentation":"Replay of OP_CLOSE found the file already complete. For edit logs at or newer than the HDFS-2991 bugfix layout version, a second OP_CLOSE is an error; only pre-0.23.1 logs (HDFS-2991 could log OP_CLOSE twice) are tolerated. The throw means the namespace state and the edit stream disagree about the file.","triggerScenarios":"Two OP_CLOSE records for the same file in logs with a post-bugfix layout version; an fsimage that already contains the closed file while edits re-close it; duplicated or mis-ordered segments in the name directories.","commonSituations":"fsimage restored from one backup and edits from another point in time; duplicate segment files left by a failed manual recovery; rollback or downgrade leaving overlapping transactions.","solutions":["Make fsimage and edit logs in all configured name directories come from the same checkpoint epoch; never mix files from different backups","Run 'hdfs namenode -recover' to skip the inconsistent transaction","Remove duplicated or overlapping segment files and let the NameNode load a clean chain"],"exampleFix":"# before: image from backup A mixed with edits from backup B -> duplicate OP_CLOSE\ncp backupA/fsimage_* /hadoop/dfs/name/current/ && cp backupB/edits_* /hadoop/dfs/name/current/\n\n# after: restore the whole current/ directory from one backup\nrm -rf /hadoop/dfs/name/current && cp -a backupA/current /hadoop/dfs/name/current","handlingStrategy":"validation","validationCode":"// image and retained segments must chain with no gap or overlap\nNNStorage s = new NNStorage(conf, dirs);\nlong imgTx = s.getMostRecentCheckpointTxId();\n// each segment's [first,last] txid parsed from its filename must start at\n// imgTx + 1 and continue contiguously; any duplicate OP_CLOSE candidate\n// shows up as an overlapping segment","typeGuard":null,"tryCatchPattern":"try {\n  loader.loadFSEdits(storage, 0);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"File is not under construction\")) {\n    // duplicate OP_CLOSE vs stale image state: restore a single-epoch backup\n    // or restart with 'hdfs namenode -recover' to skip it\n  }\n  throw e;\n}","preventionTips":["Restore the entire name directory from one backup, never image from one and edits from another","Checkpoint before upgrades and downgrades","After manual recovery, verify the segment chain before starting the NameNode"],"tags":["hdfs","namenode","edit-log","replay","op-close","hdfs-2991"],"backgroundTag":"edit-log-replay-inconsistency","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}