apache/iceberg · error · IllegalArgumentException

Unexpected command: command

Error message

Unexpected command: command

What it means

SparkWriteConf.copyOnWriteDistributionMode() maps a row-level Command (DELETE, UPDATE, MERGE) to its copy-on-write distribution mode. Any Command outside that enum set is unexpected and throws IllegalArgumentException — an internal invariant/default-case guard.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkWriteConf.java:373

    return SparkWriteUtil.copyOnWriteRequirements(
        table,
        command,
        copyOnWriteDistributionMode(command),
        fanoutWriterEnabled(),
        dataAdvisoryPartitionSize());
  }

  @VisibleForTesting
  DistributionMode copyOnWriteDistributionMode(Command command) {
    switch (command) {
      case DELETE:
        return deleteDistributionMode();
      case UPDATE:
        return updateDistributionMode();
      case MERGE:
        return copyOnWriteMergeDistributionMode();
      default:
        throw new IllegalArgumentException("Unexpected command: " + command);
    }
  }

  public SparkWriteRequirements positionDeltaRequirements(Command command) {
    if (ignoreTableDistributionAndOrdering()) {
      LOG.info("Skipping distribution/ordering: disabled per job configuration");
      return SparkWriteRequirements.EMPTY;
    }

    return SparkWriteUtil.positionDeltaRequirements(
        table,
        command,
        positionDeltaDistributionMode(command),
        fanoutWriterEnabled(),
        command == DELETE ? deleteAdvisoryPartitionSize() : dataAdvisoryPartitionSize());
  }

  @VisibleForTesting

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Only pass DELETE, UPDATE, or MERGE to this method; route other commands to their dedicated configuration methods (e.g. appendDistributionMode for writes)
  2. If a new Command value exists, upgrade the Iceberg Spark module so it is handled
  3. In custom code, switch on command yourself and only delegate supported values

Example fix

// before
DistributionMode mode = writeConf.copyOnWriteDistributionMode(command);
// after
if (command == Command.DELETE || command == Command.UPDATE || command == Command.MERGE) {
  DistributionMode mode = writeConf.copyOnWriteDistributionMode(command);
}
Defensive patterns

Strategy: validation

Validate before calling

if (command == null || (command != Command.DELETE && command != Command.UPDATE && command != Command.MERGE)) {
  throw new IllegalArgumentException("copyOnWriteDistributionMode requires DELETE/UPDATE/MERGE");
}

Type guard

boolean isRowLevelCommand = command == Command.DELETE || command == Command.UPDATE || command == Command.MERGE;

Try / catch

try {
  mode = writeConf.copyOnWriteDistributionMode(command);
} catch (IllegalArgumentException e) {
  throw new IllegalStateException("Unsupported command for CoW planning: " + command, e);
}

Prevention

When it happens

Trigger: Calling copyOnWriteDistributionMode() (directly or via copyOnWriteRequirements/checkMode) with a Command value that is not DELETE, UPDATE, or MERGE — e.g. a Command overwrite/insert variant or null.

Common situations: Custom Spark extensions or tests constructing SparkWriteConf and passing their own command; new Command enum values added upstream not yet handled by this distribution-mode method.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/426f5d665ccb1753. Report an issue: GitHub.