apache/hadoop · error · DiskBalancerException

INVALID_VOLUME

INVALID_VOLUME

Error message

Disk Balancer - Unable to find source volume: {}. SubmitPlan failed.

What it means

While translating plan steps into DiskBalancerWorkItems, createWorkPlan() resolves each step's source volume UUID against the DataNode's live storageID-to-volume map (getStorageIDToVolumeBasePathMap()). If the source volume UUID is absent, the plan references storage that no longer exists on this node, and Result.INVALID_VOLUME is thrown with the missing volume's path in the message.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DiskBalancer.java:530

   */
  private void createWorkPlan(NodePlan plan) throws DiskBalancerException {
    Preconditions.checkState(lock.isHeldByCurrentThread());

    // Cleanup any residual work in the map.
    workMap.clear();
    Map<String, String> storageIDToVolBasePathMap =
        getStorageIDToVolumeBasePathMap();

    for (Step step : plan.getVolumeSetPlans()) {
      String sourceVolUuid = step.getSourceVolume().getUuid();
      String destVolUuid = step.getDestinationVolume().getUuid();

      String sourceVolBasePath = storageIDToVolBasePathMap.get(sourceVolUuid);
      if (sourceVolBasePath == null) {
        final String errMsg = "Disk Balancer - Unable to find source volume: "
            + step.getSourceVolume().getPath() + ". SubmitPlan failed.";
        LOG.error(errMsg);
        throw new DiskBalancerException(errMsg,
            DiskBalancerException.Result.INVALID_VOLUME);
      }

      String destVolBasePath = storageIDToVolBasePathMap.get(destVolUuid);
      if (destVolBasePath == null) {
        final String errMsg = "Disk Balancer - Unable to find dest volume: "
            + step.getDestinationVolume().getPath() + ". SubmitPlan failed.";
        LOG.error(errMsg);
        throw new DiskBalancerException(errMsg,
            DiskBalancerException.Result.INVALID_VOLUME);
      }
      VolumePair volumePair = new VolumePair(sourceVolUuid,
          sourceVolBasePath, destVolUuid, destVolBasePath);
      createWorkPlan(volumePair, step);
    }
  }

  /**

View on GitHub (pinned to 2add963021)

Solutions

  1. Regenerate the plan so it reflects the current volume set, then submit.
  2. List the DataNode's current volumes (DataNode JMX FSDatasetStateInfo, `hdfs dfsadmin -report`) and confirm each step's source volume UUID still exists.
  3. If a volume was intentionally removed, discard the old plan — it cannot be patched by hand without breaking the plan hash.
  4. Verify the plan is being submitted to the same DataNode it was generated for.

Example fix

// before: submit a plan generated before a disk was replaced
diskBalancer.submitPlan(planID, version, planString, false);

// after: check every step's volumes against the live volume set first
Map<String, ?> volumes = dataset.getVolumeInfoMap(); // keyed by storageID
for (Step s : NodePlan.parseJson(planString).getVolumeSetPlans()) {
  if (!volumes.containsKey(s.getSourceVolume().getUuid())) {
    planString = generateFreshPlan(datanode); // volume set changed
    break;
  }
}
diskBalancer.submitPlan(planID, version, planString, false);
Defensive patterns

Strategy: validation

Validate before calling

Map<String, ?> volumes = dataset.getVolumeInfoMap(); // storageID -> VolumeInfo
for (Step s : NodePlan.parseJson(planString).getVolumeSetPlans()) {
  if (!volumes.containsKey(s.getSourceVolume().getUuid())) {
    // a source volume no longer exists: regenerate the plan
  }
}

Try / catch

try {
  diskBalancer.submitPlan(planID, version, plan, false);
} catch (DiskBalancerException e) {
  if (e.getResult() == DiskBalancerException.Result.INVALID_VOLUME
      && e.getMessage().contains("source volume")) {
    // volume set changed since planning: regenerate the plan
  }
}

Prevention

When it happens

Trigger: submitPlan where a step's sourceVolumeUUID is not among the DataNode's current volumes: a disk was removed, failed, or replaced between `-plan` and `-execute`; the plan was generated against a different node's volume set; storage IDs changed after a reformat.

Common situations: Dead disk swapped out before the plan was executed; hot-removed volume; DataNode restarted with a reduced dfs.datanode.data.dir list; submitting a plan file that belongs to another machine.

Related errors


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