apache/iceberg · error · IllegalArgumentException
Unsupported operation mode: + mode
Error message
Unsupported operation mode: + mode
What it means
SparkRowLevelOperationBuilder.build() maps the resolved RowLevelOperationMode to either SparkCopyOnWriteOperation or SparkPositionDeltaOperation. Any mode other than COPY_ON_WRITE or MERGE_ON_READ hits the default branch and throws this IllegalArgumentException. There is no third row-level write mode in the Iceberg Spark integration.
Source
Thrown at spark/v4.0/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
- Set mode properties to exactly 'copy-on-write' or 'merge-on-read' (case handled by fromName, but no other values are valid).
- Inspect table properties with DESCRIBE TABLE / metadata and remove or correct the bad *.*.mode keys.
- Remove the invalid property to fall back to the default mode for the command.
- Check RowLevelOperationMode.fromName() for accepted names before setting properties.
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
Set<String> valid = Set.of("copy-on-write", "merge-on-read");
String mode = props.getOrDefault("write.merge.mode", "copy-on-write");
if (!valid.contains(mode.toLowerCase(Locale.ROOT))) {
throw new IllegalArgumentException("Bad write mode: " + mode);
} Try / catch
try { RowLevelOperation op = builder.build(); } catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unsupported operation mode")) { fixTableModeProperty(e); }
else throw e;
} Prevention
- Set write.*.mode properties only to 'copy-on-write' or 'merge-on-read'
- Read properties back via DESCRIBE TABLE after edits
- Avoid hand-editing table metadata JSON
When it happens
Trigger: Table properties such as write.update.mode / write.delete.mode / write.merge.mode are set to an unrecognized string that RowLevelOperationMode.fromName() resolves to a non-standard mode value, then passed to build().
Common situations: Typos in mode properties (e.g. 'copy-on-write ', 'MOR', 'cow'); hand-edited table properties; property values written by other engines or older versions with different names.
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
- Cannot parse order: parser is not an Iceberg ExtendedParser
- Table does not implement %s: %s (%s)
- Cannot use catalog %s(%s): not a TableCatalog
- Invalid session catalog: sparkSessionCatalog
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/83ad479dbdb067e4.
Report an issue: GitHub.