apache/hadoop · error · DiskBalancerException

INVALID_MOVE

INVALID_MOVE

Error message

Disk Balancer - Source and destination volumes are same: {}

What it means

createWorkPlan(VolumePair, Step) rejects a plan step whose source volume UUID equals its destination volume UUID with Result.INVALID_MOVE. Copying data from a volume to itself is a no-op, so such a step means the plan is degenerate — usually planner output on an unusual volume layout or a hand-crafted plan. Note it is logged at WARN but still aborts submitPlan.

Source

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

          blockMover.setRunnable();
          blockMover.copyBlocks(entry.getKey(), entry.getValue());
        }
      }
    });
  }

  /**
   * Insert work items to work map.
   * @param volumePair - VolumePair
   * @param step - Move Step
   */
  private void createWorkPlan(final VolumePair volumePair, Step step)
      throws DiskBalancerException {
    if (volumePair.getSourceVolUuid().equals(volumePair.getDestVolUuid())) {
      final String errMsg = "Disk Balancer - Source and destination volumes " +
          "are same: " + volumePair.getSourceVolUuid();
      LOG.warn(errMsg);
      throw new DiskBalancerException(errMsg,
          DiskBalancerException.Result.INVALID_MOVE);
    }
    long bytesToMove = step.getBytesToMove();
    // In case we have a plan with more than
    // one line of same VolumePair
    // we compress that into one work order.
    if (workMap.containsKey(volumePair)) {
      bytesToMove += workMap.get(volumePair).getBytesToCopy();
    }

    DiskBalancerWorkItem work = new DiskBalancerWorkItem(bytesToMove, 0);

    // all these values can be zero, if so we will use
    // values from configuration.
    work.setBandwidth(step.getBandwidth());
    work.setTolerancePercent(step.getTolerancePercent());
    work.setMaxDiskErrors(step.getMaxDiskErrors());
    workMap.put(volumePair, work);

View on GitHub (pinned to 2add963021)

Solutions

  1. Regenerate the plan; a fresh planner run on the current volume report usually will not emit a self-referencing step.
  2. Inspect the plan JSON, remove or fix steps where both sides share a UUID, and recompute the planID (sha1 of the plan bytes) since editing changes the hash.
  3. If the planner reproducibly emits same-volume steps for this node, attach the node volume report and file a Hadoop JIRA.

Example fix

// before: submit plan that contains a same-volume step
diskBalancer.submitPlan(planID, version, planString, false);

// after: filter degenerate steps client-side before submitting
NodePlan plan = NodePlan.parseJson(planString);
plan.setVolumeSetPlans(plan.getVolumeSetPlans().stream()
    .filter(s -> !s.getSourceVolume().getUuid()
        .equals(s.getDestinationVolume().getUuid()))
    .collect(Collectors.toList()));
String filtered = plan.toJson();
String newPlanId = DigestUtils.sha1Hex(filtered.getBytes(StandardCharsets.UTF_8));
diskBalancer.submitPlan(newPlanId, version, filtered, false);
Defensive patterns

Strategy: validation

Validate before calling

for (Step s : NodePlan.parseJson(planString).getVolumeSetPlans()) {
  if (s.getSourceVolume().getUuid().equals(s.getDestinationVolume().getUuid())) {
    // degenerate step: reject or filter the plan before submitting
  }
}

Try / catch

try {
  diskBalancer.submitPlan(planID, version, plan, false);
} catch (DiskBalancerException e) {
  if (e.getResult() == DiskBalancerException.Result.INVALID_MOVE) {
    // plan contains a self-move: filter the step, recompute planID hash, resubmit
  }
}

Prevention

When it happens

Trigger: A NodePlan step whose sourceVolumeUUID and destinationVolumeUUID are identical: emitted by the planner when one volume is somehow selected as both most- and least-used, or written manually into the plan JSON.

Common situations: Single-volume or perfectly balanced nodes producing degenerate planner output; hand-edited plans where a volume UUID was pasted into both sides; planner edge cases on tiny or unusual volume sets.

Related errors


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