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

  1. Set write.isolation-level to 'serializable' or 'snapshot' (case-insensitive) on the table or Spark conf
  2. If set programmatically, pass only IsolationLevel.SERIALIZABLE or IsolationLevel.SNAPSHOT
  3. 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

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


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