apache/iceberg · error · IllegalStateException

Cannot process unknown snapshot operation: %s (snapshot id %

Error message

Cannot process unknown snapshot operation: %s (snapshot id %s)

What it means

The micro-batch planner's shouldProcess switch handles only a fixed set of snapshot operations (append, delete, overwrite with its own error, replace). Any DataOperation value outside that set reaches the default branch and throws IllegalStateException. This guards against forward-compatibility gaps where the table was written by a newer Iceberg version with a new operation type.

Source

Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/source/BaseSparkMicroBatchPlanner.java:76

        return true;
      case DataOperations.REPLACE:
        return false;
      case DataOperations.DELETE:
        Preconditions.checkState(
            readConf.streamingSkipDeleteSnapshots(),
            "Cannot process delete snapshot: %s, to ignore deletes, set %s=true",
            snapshot.snapshotId(),
            SparkReadOptions.STREAMING_SKIP_DELETE_SNAPSHOTS);
        return false;
      case DataOperations.OVERWRITE:
        Preconditions.checkState(
            readConf.streamingSkipOverwriteSnapshots(),
            "Cannot process overwrite snapshot: %s, to ignore overwrites, set %s=true",
            snapshot.snapshotId(),
            SparkReadOptions.STREAMING_SKIP_OVERWRITE_SNAPSHOTS);
        return false;
      default:
        throw new IllegalStateException(
            String.format(
                "Cannot process unknown snapshot operation: %s (snapshot id %s)",
                op.toLowerCase(Locale.ROOT), snapshot.snapshotId()));
    }
  }

  /**
   * Get the next snapshot skipping over rewrite and delete snapshots. Async must handle nulls.
   *
   * @param curSnapshot the current snapshot
   * @return the next valid snapshot (not a rewrite or delete snapshot), returns null if all
   *     remaining snapshots should be skipped.
   */
  protected Snapshot nextValidSnapshot(Snapshot curSnapshot) {
    Snapshot nextSnapshot;
    // if there were no valid snapshots, check for an initialOffset again
    if (curSnapshot == null) {
      StreamingOffset startingOffset =

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Upgrade the reader's Iceberg runtime to at least the version used by the writer.
  2. Identify the snapshot id from the message and inspect its operation via table.snapshots().
  3. If a custom writer produced the snapshot, switch it to standard operations (append/replace/overwrite/delete).
  4. As a workaround, expire the offending snapshot so streaming continues from a valid one.

Example fix

// before
// reader Iceberg 1.4 encounters op from Iceberg 1.7
// after
// upgrade dependency
implementation 'org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.7.0'
Defensive patterns

Strategy: validation

Validate before calling

// check snapshot operation before relying on the stream
for (Snapshot s : table.snapshots()) {
  String op = s.operation();
  if (!Set.of("append","delete","overwrite","replace").contains(op)) {
    throw new IllegalStateException("unsupported op: " + op);
  }
}

Try / catch

try { batch = plan(); } catch (IllegalStateException e) {
  if (e.getMessage().contains("unknown snapshot operation")) upgradeRuntimeAndRestart();
  else throw e;
}

Prevention

When it happens

Trigger: Streaming read encounters a snapshot whose operation() is not append/delete/overwrite/replace — e.g. a snapshot produced by a newer Iceberg writer introducing a new DataOperation, or a corrupted snapshot record.

Common situations: Mixed Iceberg versions: writer cluster newer than reader; manually crafted snapshots via API; snapshots produced by third-party engines using unusual operations.

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/56dde11e028ad213. Report an issue: GitHub.