{"record":{"id":"83596637367aaba4","repo":"apache/hadoop","slug":"invalid-plan","errorCode":"INVALID_PLAN","errorMessage":"Invalid plan.","messagePattern":"Invalid plan\\.","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":448,"sourceCode":"      LOG.error(\"Disk Balancer - Invalid plan version.\");\n      throw new DiskBalancerException(\"Invalid plan version.\",\n          DiskBalancerException.Result.INVALID_PLAN_VERSION);\n    }\n  }\n\n  /**\n   * Verifies that plan matches the SHA-1 provided by the client.\n   *\n   * @param planID - SHA-1 Hex Bytes\n   * @param plan   - Plan String\n   * @throws DiskBalancerException\n   */\n  private NodePlan verifyPlanHash(String planID, String plan)\n      throws DiskBalancerException {\n    final long sha1Length = 40;\n    if (plan == null || plan.length() == 0) {\n      LOG.error(\"Disk Balancer -  Invalid plan.\");\n      throw new DiskBalancerException(\"Invalid plan.\",\n          DiskBalancerException.Result.INVALID_PLAN);\n    }\n\n    if ((planID == null) ||\n        (planID.length() != sha1Length) ||\n        !DigestUtils.sha1Hex(plan.getBytes(StandardCharsets.UTF_8))\n            .equalsIgnoreCase(planID)) {\n      LOG.error(\"Disk Balancer - Invalid plan hash.\");\n      throw new DiskBalancerException(\"Invalid or mis-matched hash.\",\n          DiskBalancerException.Result.INVALID_PLAN_HASH);\n    }\n\n    try {\n      return NodePlan.parseJson(plan);\n    } catch (IOException ex) {\n      throw new DiskBalancerException(\"Parsing plan failed.\", ex,\n          DiskBalancerException.Result.MALFORMED_PLAN);\n    }","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DiskBalancer.java#L430-L466","documentation":"DiskBalancerException with Result.INVALID_PLAN from DiskBalancer.verifyPlanHash: the submitted plan string is null or empty. Before any hash comparison or JSON parsing happens, the DataNode rejects a plan payload with no content - meaning the client sent no plan data at all, not merely a bad one.","triggerScenarios":"'hdfs diskbalancer -execute' where the plan data read from the plan file is empty: empty/truncated plan file, wrong path resolving to a zero-byte file, or API callers (submitPlan) passing null/empty planData programmatically.","commonSituations":"Interrupted plan generation leaving a 0-byte plan file; passing a directory or wrong filename to -execute; scripts that capture command output into the plan file incorrectly; programmatic use of DiskBalancer.submitPlan with an unread plan.","solutions":["Inspect the plan file: ls -l and head the JSON - it must be non-empty and start with the NodePlan JSON structure","Regenerate the plan with 'hdfs diskbalancer -plan <node>' and execute the newly written file","If calling submitPlan programmatically, read the plan file fully into planData before submitting and assert non-empty"],"exampleFix":"# before: zero-byte/truncated plan -> INVALID_PLAN\nls -l /system/diskbalancer/node-plan.json   # 0 bytes\nhdfs diskbalancer -execute /system/diskbalancer/node-plan.json\n\n# after: regenerate and verify content before executing\nhdfs diskbalancer -plan <datanode>\nhead -c 200 /system/diskbalancer/<node>-plan.json   # sane JSON?\nhdfs diskbalancer -execute /system/diskbalancer/<node>-plan.json","handlingStrategy":"validation","validationCode":"// Reject empty plans before submission\nString planData = new String(Files.readAllBytes(Paths.get(planFile)),\n    StandardCharsets.UTF_8);\nif (planData == null || planData.trim().isEmpty()) {\n  throw new IllegalArgumentException(\n      \"Plan file empty: \" + planFile + \" - regenerate with 'hdfs diskbalancer -plan'\");\n}\ndiskBalancer.submitPlan(planId, planVersion, planFile, planData, force);","typeGuard":null,"tryCatchPattern":"try {\n  diskBalancer.submitPlan(planId, planVersion, planFile, planData, force);\n} catch (DiskBalancerException e) {\n  if (e.getResult() == DiskBalancerException.Result.INVALID_PLAN\n      && (planData == null || planData.isEmpty())) {\n    // payload was empty: regenerate the plan file and resubmit non-empty data\n  }\n}","preventionTips":["Sanity-check plan files (non-zero size, starts with '{') before -execute","Capture 'hdfs diskbalancer -plan' output to its own file without piping through filters that can empty it","In automation, assert planData.trim().length() > 0 before calling submitPlan"],"tags":["hdfs","diskbalancer","empty-payload","plan-validation"],"backgroundTag":"required-parameter-missing","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}