apache/iceberg · error · IllegalArgumentException

Unsupported command: + command

Error message

Unsupported command: + command

What it means

The mode() helper in SparkRowLevelOperationBuilder reads the write.*.mode table property keyed by the command type (DELETE, UPDATE, MERGE). If the incoming RowLevelOperation command is none of these, the switch's default branch throws this IllegalArgumentException because there is no mode property defined for it.

Source

Thrown at spark/v4.0/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. Upgrade iceberg-spark to a version that supports the command being executed.
  2. Use only DELETE, UPDATE, or MERGE commands with this row-level operation builder.
  3. If adding a new command, add a case to the switch mapping it to its write.*.mode property.
  4. Verify which command reaches the builder via the query plan if unsure.
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(command instanceof Delete) && !(command instanceof Update) && !(command instanceof Merge)) {
  throw new IllegalArgumentException("Command not supported by Iceberg row-level ops: " + command);
}

Type guard

boolean supported(Command c) { return c instanceof Delete || c instanceof Update || c instanceof Merge; }

Try / catch

try { RowLevelOperation op = builder.build(); } catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Unsupported command")) { throw new IllegalStateException("Upgrade iceberg-spark for this command", e); }
  throw e;
}

Prevention

When it happens

Trigger: build() calls mode(properties, command) with a Command implementation that is not DELETE, UPDATE, or MERGE — e.g. a custom or newly introduced Spark row-level command not yet handled by this builder.

Common situations: Running newer Spark commands against an older iceberg-spark module that lacks the case; custom RowLevelOperation subclasses; internal API misuse.

Related errors


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