{"record":{"id":"b02150175f323add","repo":"apache/hadoop","slug":"previous-and-previous-tmp-cannot-exist-together","errorCode":null,"errorMessage":"previous and previous.tmp cannot exist together.","messagePattern":"previous and previous\\.tmp cannot exist together\\.","errorType":"exception","errorClass":"InconsistentFSStateException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/Storage.java","lineNumber":762,"sourceCode":"                                               \"too many temporary directories.\");\n\n      // # of temp dirs == 1 should either recover or complete a transition\n      if (hasCheckpointTmp) {\n        return hasCurrent ? StorageState.COMPLETE_CHECKPOINT\n                          : StorageState.RECOVER_CHECKPOINT;\n      }\n\n      if (hasFinalizedTmp) {\n        if (hasPrevious)\n          throw new InconsistentFSStateException(root,\n                                                 STORAGE_DIR_PREVIOUS + \" and \" + STORAGE_TMP_FINALIZED\n                                                 + \"cannot exist together.\");\n        return StorageState.COMPLETE_FINALIZE;\n      }\n\n      if (hasPreviousTmp) {\n        if (hasPrevious)\n          throw new InconsistentFSStateException(root,\n                                                 STORAGE_DIR_PREVIOUS + \" and \" + STORAGE_TMP_PREVIOUS\n                                                 + \" cannot exist together.\");\n        if (hasCurrent)\n          return StorageState.COMPLETE_UPGRADE;\n        return StorageState.RECOVER_UPGRADE;\n      }\n      \n      assert hasRemovedTmp : \"hasRemovedTmp must be true\";\n      if (!(hasCurrent ^ hasPrevious))\n        throw new InconsistentFSStateException(root,\n                                               \"one and only one directory \" + STORAGE_DIR_CURRENT \n                                               + \" or \" + STORAGE_DIR_PREVIOUS \n                                               + \" must be present when \" + STORAGE_TMP_REMOVED\n                                               + \" exists.\");\n      if (hasCurrent)\n        return StorageState.COMPLETE_ROLLBACK;\n      return StorageState.RECOVER_ROLLBACK;\n    }","sourceCodeStart":744,"sourceCodeEnd":780,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/Storage.java#L744-L780","documentation":"When previous.tmp exists, an upgrade completion is pending (previous.tmp is the renamed-away old current/, destined to become previous/; normal outcomes are COMPLETE_UPGRADE with current/ present or RECOVER_UPGRADE without). If previous/ already exists too, the rename target is occupied — a duplicate 'previous' — and Storage.analyzeStorage throws InconsistentFSStateException('previous and previous.tmp cannot exist together.').","triggerScenarios":"A crash during the upgrade completion window together with a previous/ that appeared from outside the state machine: restored from backup, copied in by hand, or left by an earlier interrupted upgrade cycle.","commonSituations":"Repeatedly interrupted upgrades; operators copying previous/ back 'to be safe' before restarting; storage snapshot reverted to a mid-upgrade point while another marker survived.","solutions":["Stop the daemon and back up the storage directory","Keep exactly one 'previous' artifact: to let the upgrade complete, remove previous/ and keep previous.tmp (boot runs COMPLETE_UPGRADE when current/ exists); to keep the existing previous/, remove previous.tmp","Restart the daemon and verify it reaches NORMAL"],"exampleFix":"# previous/ AND previous.tmp both present after crashed upgrade\n# goal: complete upgrade (current/ present)\nmv /dfs/nn/previous /backup/previous.old\n# restart namenode -> COMPLETE_UPGRADE renames previous.tmp -> previous","handlingStrategy":"try-catch","validationCode":"File root = sd.getRoot();\nboolean hasPrev = new File(root, \"previous\").exists();\nboolean hasPrevTmp = new File(root, \"previous.tmp\").exists();\nif (hasPrev && hasPrevTmp) {\n  throw new IOException(\"previous/ and previous.tmp coexist in \" + root\n      + \"; remove the stale one (keep previous.tmp to complete the upgrade)\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  daemon.start();\n} catch (InconsistentFSStateException e) {\n  if (e.getMessage().contains(\"previous.tmp\")) {\n    haltWithRunbook(\"Crashed upgrade completion: remove previous/ (complete) or \"\n        + \"previous.tmp (keep existing previous/); back up first\");\n  } else throw e;\n}","preventionTips":["Do not copy previous/ back into a storage dir that still has previous.tmp","Let the daemon finish upgrade recovery before taking backups or starting new transitions","Document the intended end-state (upgraded vs rolled back) before manual recovery"],"tags":["hdfs","storage","upgrade","inconsistent-state","recovery","rename"],"backgroundTag":"inconsistent-storage-state","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}