apache/iceberg · error · IllegalArgumentException

Invalid isolation level

Error message

Invalid isolation level: %s

What it means

IsolationLevel.fromName parses a string into the IsolationLevel enum case-insensitively; a null input gets a dedicated message, and any name not matching SERIALIZABLE or SNAPSHOT rethrows IllegalArgumentException with the offending value and the underlying cause.

Solutions

  1. Set the value to exactly 'serializable' or 'snapshot' (any case)
  2. Trim whitespace/newlines from the configured value
  3. Handle null by defaulting to SERIALIZABLE explicitly in calling code

Example fix

// before
conf.set("isolation-level", "read-committed");
// after
conf.set("isolation-level", "snapshot");
Defensive patterns

Strategy: validation

Validate before calling

String v = raw == null ? null : raw.trim();
boolean valid = "serializable".equalsIgnoreCase(v) || "snapshot".equalsIgnoreCase(v);
if (!valid) throw new IllegalArgumentException("Bad isolation level: " + raw);

Try / catch

try {
  IsolationLevel level = IsolationLevel.fromName(raw);
} catch (IllegalArgumentException e) {
  level = IsolationLevel.SERIALIZABLE; // documented default
}

Prevention

When it happens

Trigger: Passing an isolation-level string (e.g., table property or config value) that is neither 'serializable' nor 'snapshot' (case-insensitive), or null.

Common situations: Typo in table properties like write.wap / retry config; value like 'SERIALIZABLE ' with trailing whitespace; users supplying 'strict' or 'read-committed' which Iceberg does not support.

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/64b813ad56b6b645. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/IsolationLevel.java:48

 * isolation is beneficial for environments with many concurrent writers.
 *
 * <p>The serializable isolation level guarantees that an ongoing UPDATE/DELETE/MERGE operation
 * fails if a concurrent transaction commits a new file that might contain rows matching the
 * condition used in UPDATE/DELETE/MERGE. For example, if there is an ongoing update on a subset of
 * rows and a concurrent transaction adds a new file with records that potentially match the update
 * condition, the update operation must fail under the serializable isolation but can still commit
 * under the snapshot isolation.
 */
public enum IsolationLevel {
  SERIALIZABLE,
  SNAPSHOT;

  public static IsolationLevel fromName(String levelName) {
    Preconditions.checkArgument(levelName != null, "Invalid isolation level: null");
    try {
      return IsolationLevel.valueOf(levelName.toUpperCase(Locale.ROOT));
    } catch (IllegalArgumentException e) {
      throw new IllegalArgumentException(
          String.format("Invalid isolation level: %s", levelName), e);
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)