{"record":{"id":"591b2defc8ce57b0","repo":"apache/hadoop","slug":"old-plan-submitted","errorCode":"OLD_PLAN_SUBMITTED","errorMessage":"Plan was generated more than {} ago","messagePattern":"Plan was generated more than (.+?) ago","errorType":"exception","errorClass":"DiskBalancerException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DiskBalancer.java","lineNumber":488,"sourceCode":"   * Verifies that this plan is not older than 24 hours.\n   *\n   * @param plan - Node Plan\n   */\n  private void verifyTimeStamp(NodePlan plan) throws DiskBalancerException {\n    long now = Time.now();\n    long planTime = plan.getTimeStamp();\n\n    if ((planTime + planValidityInterval) < now) {\n      String planValidity = config.get(\n          DFSConfigKeys.DFS_DISK_BALANCER_PLAN_VALID_INTERVAL,\n          DFSConfigKeys.DFS_DISK_BALANCER_PLAN_VALID_INTERVAL_DEFAULT);\n      if (planValidity.matches(\"[0-9]$\")) {\n        planValidity += \"ms\";\n      }\n      String errorString = \"Plan was generated more than \" + planValidity\n          + \" ago\";\n      LOG.error(\"Disk Balancer - \" + errorString);\n      throw new DiskBalancerException(errorString,\n          DiskBalancerException.Result.OLD_PLAN_SUBMITTED);\n    }\n  }\n\n  /**\n   * Verify Node UUID.\n   *\n   * @param plan - Node Plan\n   */\n  private void verifyNodeUUID(NodePlan plan) throws DiskBalancerException {\n    if ((plan.getNodeUUID() == null) ||\n        !plan.getNodeUUID().equals(this.dataNodeUUID)) {\n      LOG.error(\"Disk Balancer - Plan was generated for another node.\");\n      throw new DiskBalancerException(\n          \"Plan was generated for another node.\",\n          DiskBalancerException.Result.DATANODE_ID_MISMATCH);\n    }\n  }","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DiskBalancer.java#L470-L506","documentation":"DiskBalancer refuses to execute a plan older than dfs.disk.balancer.plan.valid.interval (default '2d'). A plan is a point-in-time snapshot of volume usage; running a stale one would move data according to outdated numbers. verifyTimeStamp() throws DiskBalancerException with Result.OLD_PLAN_SUBMITTED when plan timestamp + validity interval is still in the past.","triggerScenarios":"Calling submitPlan(planID, version, plan, skipDateCheck=false) when plan.getTimeStamp() + planValidityInterval < Time.now() — i.e., the plan file was generated more than the configured interval (default 48 hours) before submission.","commonSituations":"Generating a plan on Friday and executing it Monday; batch tooling that generates plans for many nodes and then submits them slowly; a deliberately tiny validity interval such as '1000' (interpreted as ms); clock skew between the plan-generation host and the DataNode making a fresh plan look old.","solutions":["Regenerate the plan immediately before executing: `hdfs diskbalancer -plan <host:port>` followed by `hdfs diskbalancer -execute <planfile>`.","If the delay is intentional, raise dfs.disk.balancer.plan.valid.interval (e.g., '7d') in hdfs-site.xml on the DataNode and restart it.","Programmatic submitters that accept staleness can pass skipDateCheck=true to DiskBalancer.submitPlan.","Verify NTP on the plan-generation host and the DataNode to rule out clock skew."],"exampleFix":"// before: submit a day-old plan with the date check enabled\ndiskBalancer.submitPlan(planID, version, planString, false);\n\n// after: check age client-side and regenerate when stale\nNodePlan p = NodePlan.parseJson(planString);\nlong validityMs = TimeUnit.DAYS.toMillis(2); // mirror dfs.disk.balancer.plan.valid.interval\nif (p.getTimeStamp() + validityMs < Time.now()) {\n  planString = generateFreshPlan(datanode);\n}\ndiskBalancer.submitPlan(planID, version, planString, false);","handlingStrategy":"validation","validationCode":"long validityMs = TimeUnit.DAYS.toMillis(2); // mirror dfs.disk.balancer.plan.valid.interval\nNodePlan p = NodePlan.parseJson(planString);\nif (p.getTimeStamp() + validityMs < Time.now()) {\n  // plan is stale: regenerate before submitting\n}","typeGuard":null,"tryCatchPattern":"try {\n  diskBalancer.submitPlan(planID, version, plan, false);\n} catch (DiskBalancerException e) {\n  if (e.getResult() == DiskBalancerException.Result.OLD_PLAN_SUBMITTED) {\n    plan = regeneratePlan(datanode);\n    diskBalancer.submitPlan(newPlanID, version, plan, false); // one resubmit with a fresh plan\n  }\n}","preventionTips":["Run `hdfs diskbalancer -execute` immediately after `-plan` for the same node","For batch operations across many nodes, generate each plan just before its execution rather than all upfront","NTP-sync the plan host and DataNodes; account for configured dfs.disk.balancer.plan.valid.interval in scheduling"],"tags":["disk-balancer","plan-expiry","configuration","hdfs","datanode"],"backgroundTag":"expired-plan-rejected","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}