apache/iceberg · error · IllegalArgumentException
Unsupported isolation level: + isolationLevel
Error message
Unsupported isolation level: + isolationLevel
What it means
SparkWrite's OverwriteByFilter/OverwritePartitions commit only supports Serializable and Snapshot isolation levels. An IsolationLevel value outside this switch (default branch) is rejected with IllegalArgumentException before any commit operation runs.
Source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/source/SparkWrite.java:484
int numAddedFiles = 0;
for (DataFile file : files(messages)) {
numAddedFiles += 1;
overwriteFiles.addFile(file);
}
// the scan may be null if the optimizer replaces it with an empty relation (e.g. false cond)
// no validation is needed in this case as the command does not depend on the table state
if (scan != null) {
switch (isolationLevel) {
case SERIALIZABLE:
commitWithSerializableIsolation(overwriteFiles, numOverwrittenFiles, numAddedFiles);
break;
case SNAPSHOT:
commitWithSnapshotIsolation(overwriteFiles, numOverwrittenFiles, numAddedFiles);
break;
default:
throw new IllegalArgumentException("Unsupported isolation level: " + isolationLevel);
}
} else {
commitOperation(
overwriteFiles,
String.format(
Locale.ROOT, "overwrite with %d new data files (no validation)", numAddedFiles));
}
}
private void commitWithSerializableIsolation(
OverwriteFiles overwriteFiles, int numOverwrittenFiles, int numAddedFiles) {
Long scanSnapshotId = scan.snapshotId();
if (scanSnapshotId != null) {
overwriteFiles.validateFromSnapshot(scanSnapshotId);
}
Expression conflictDetectionFilter = conflictDetectionFilter();View on GitHub (pinned to 86d9c8fc54)
Solutions
- Set write.isolation-level to 'serializable' or 'snapshot' (case-insensitive) on the table or Spark conf
- If set programmatically, pass only IsolationLevel.SERIALIZABLE or IsolationLevel.SNAPSHOT
- Verify no engine/connector upgrade introduced an unrecognized isolation level
Example fix
// before
ALTER TABLE t SET TBLPROPERTIES ('write.isolation-level'='strict');
// after
ALTER TABLE t SET TBLPROPERTIES ('write.isolation-level'='serializable'); Defensive patterns
Strategy: validation
Validate before calling
String level = table.properties().getOrDefault("write.isolation-level", "serializable").toLowerCase(Locale.ROOT);
if (!level.equals("serializable") && !level.equals("snapshot")) {
throw new IllegalArgumentException("write.isolation-level must be 'serializable' or 'snapshot', got: " + level);
} Try / catch
try {
write.commit();
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unsupported isolation level")) {
// correct the write.isolation-level property and retry
} else throw e;
} Prevention
- Only set write.isolation-level to 'serializable' or 'snapshot'
- Validate table properties after any catalog migration or version upgrade
- Parse isolation levels through the same code path the writer uses before committing
When it happens
Trigger: Calling commit on a SparkWrite overwrite operation whose write.isolation-level property resolves to something other than 'serializable' or 'snapshot'.
Common situations: Typo'd or invalid value for write.isolation-level table property or spark SQL conf; programmatic construction of SparkWrite with a custom IsolationLevel; version drift where a new level was added upstream but not handled.
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 isolation level: ${isolationLevel}
- Unsupported operation mode: ${mode}
- Unsupported command: ${command}
- Unsupported type: {primitive}
- Unsupported isolation level: " + isolationLevel
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/6434e52f7d8ab3d1.
Report an issue: GitHub.