apache/iceberg · error · IllegalArgumentException

Unsupported command: ${command}

Error message

Unsupported command: ${command}

What it means

SparkRowLevelOperationBuilder.mode() resolves which table property to read the row-level mode from. Only DELETE, UPDATE, and MERGE Spark Commands are recognized; any other command reaches the default branch and throws IllegalArgumentException.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/SparkRowLevelOperationBuilder.java:89

        throw new IllegalArgumentException("Unsupported operation mode: " + mode);
    }
  }

  private RowLevelOperationMode mode(Map<String, String> properties, Command command) {
    String modeName;

    switch (command) {
      case DELETE:
        modeName = properties.getOrDefault(DELETE_MODE, DELETE_MODE_DEFAULT);
        break;
      case UPDATE:
        modeName = properties.getOrDefault(UPDATE_MODE, UPDATE_MODE_DEFAULT);
        break;
      case MERGE:
        modeName = properties.getOrDefault(MERGE_MODE, MERGE_MODE_DEFAULT);
        break;
      default:
        throw new IllegalArgumentException("Unsupported command: " + command);
    }

    return RowLevelOperationMode.fromName(modeName);
  }

  private IsolationLevel isolationLevel(Map<String, String> properties, Command command) {
    String levelName;

    switch (command) {
      case DELETE:
        levelName = properties.getOrDefault(DELETE_ISOLATION_LEVEL, DELETE_ISOLATION_LEVEL_DEFAULT);
        break;
      case UPDATE:
        levelName = properties.getOrDefault(UPDATE_ISOLATION_LEVEL, UPDATE_ISOLATION_LEVEL_DEFAULT);
        break;
      case MERGE:
        levelName = properties.getOrDefault(MERGE_ISOLATION_LEVEL, MERGE_ISOLATION_LEVEL_DEFAULT);
        break;

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use a supported command: DELETE FROM, UPDATE, or MERGE INTO against the Iceberg table.
  2. Upgrade Iceberg to a version that supports the command in SparkRowLevelOperationBuilder.
  3. If extending Iceberg, add a case for the new command to the switch in mode().
Defensive patterns

Strategy: validation

Validate before calling

if (!(command instanceof DeleteFromTable || command instanceof UpdateTable || command instanceof MergeIntoTable)) {
  throw new IllegalArgumentException("Iceberg row-level ops support only DELETE/UPDATE/MERGE, got " + command.getClass());
}

Try / catch

try {
  builder.mode(properties, command);
} catch (IllegalArgumentException e) {
  // fall back to plain append/overwrite path
}

Prevention

When it happens

Trigger: build() is invoked for a RowLevelOperation whose Command is not DELETE, UPDATE, or MERGE — e.g. a custom or newly added Spark command wired to the Iceberg row-level operation builder without extending the switch.

Common situations: Running a newly introduced Spark command (or a third-party command) against an Iceberg version whose builder predates support for it; plugging Iceberg's builder into a custom DML command.

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/0d9dd2f7f41ab28e. Report an issue: GitHub.