apache/iceberg · error · IllegalArgumentException
Unsupported operation mode: ${mode}
Error message
Unsupported operation mode: ${mode} What it means
SparkRowLevelOperationBuilder.build() maps the resolved RowLevelOperationMode to an operation. Only COPY_ON_WRITE and MERGE_ON_READ are supported; any other mode value (e.g. a mode parsed from an unrecognized property string) hits the default branch and throws IllegalArgumentException.
Source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/SparkRowLevelOperationBuilder.java:71
SparkRowLevelOperationBuilder(
SparkSession spark, Table table, String branch, RowLevelOperationInfo info) {
this.spark = spark;
this.table = table;
this.branch = branch;
this.info = info;
this.mode = mode(table.properties(), info.command());
this.isolationLevel = isolationLevel(table.properties(), info.command());
}
@Override
public RowLevelOperation build() {
switch (mode) {
case COPY_ON_WRITE:
return new SparkCopyOnWriteOperation(spark, table, branch, info, isolationLevel);
case MERGE_ON_READ:
return new SparkPositionDeltaOperation(spark, table, branch, info, isolationLevel);
default:
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);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check the table properties write.delete.mode, write.update.mode, write.merge.mode and set them only to 'copy-on-write' or 'merge-on-read'.
- Fix typos in the mode property value (mode comparison is by exact name).
- Align client and table Iceberg versions so RowLevelOperationMode.fromName cannot yield an unknown value.
Example fix
// before
ALTER TABLE t SET TBLPROPERTIES ('write.merge.mode' = 'mor');
// after
ALTER TABLE t SET TBLPROPERTIES ('write.merge.mode' = 'merge-on-read'); Defensive patterns
Strategy: validation
Validate before calling
for (String key : List.of("write.delete.mode", "write.update.mode", "write.merge.mode")) {
String v = table.properties().get(key);
if (v != null && !v.equals("copy-on-write") && !v.equals("merge-on-read")) {
throw new IllegalArgumentException("Invalid " + key + ": " + v);
}
} Try / catch
try {
RowLevelOperation op = builder.build();
} catch (IllegalArgumentException e) {
logger.error("Check write.*.mode table properties", e);
} Prevention
- Only set write.*.mode to 'copy-on-write' or 'merge-on-read'.
- Avoid hand-editing table properties without validating values.
- Check properties after catalog migrations that may copy stale values.
When it happens
Trigger: Calling build() when the mode resolved from table properties (write.delete.mode / write.update.mode / write.merge.mode) is not COPY_ON_WRITE or MERGE_ON_READ — typically RowLevelOperationMode.fromName returned null or an unknown mode.
Common situations: A typo'd or unsupported value for the write.*.mode table property, or a newer mode enum value from a different Iceberg version being passed to an older builder.
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
- Unsupported command: ${command}
- Unsupported isolation level: ${isolationLevel}
- Unsupported isolation level: + isolationLevel
- Unsupported aggregate type:
- Invalid operation for BoundLiteralPredicate:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/80f95a56ad83419c.
Report an issue: GitHub.