{"record":{"id":"56dde11e028ad213","repo":"apache/iceberg","slug":"cannot-process-unknown-snapshot-operation-s-sna","errorCode":null,"errorMessage":"Cannot process unknown snapshot operation: %s (snapshot id %s)","messagePattern":"Cannot process unknown snapshot operation: (.+?) \\(snapshot id (.+?)\\)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/source/BaseSparkMicroBatchPlanner.java","lineNumber":76,"sourceCode":"        return true;\n      case DataOperations.REPLACE:\n        return false;\n      case DataOperations.DELETE:\n        Preconditions.checkState(\n            readConf.streamingSkipDeleteSnapshots(),\n            \"Cannot process delete snapshot: %s, to ignore deletes, set %s=true\",\n            snapshot.snapshotId(),\n            SparkReadOptions.STREAMING_SKIP_DELETE_SNAPSHOTS);\n        return false;\n      case DataOperations.OVERWRITE:\n        Preconditions.checkState(\n            readConf.streamingSkipOverwriteSnapshots(),\n            \"Cannot process overwrite snapshot: %s, to ignore overwrites, set %s=true\",\n            snapshot.snapshotId(),\n            SparkReadOptions.STREAMING_SKIP_OVERWRITE_SNAPSHOTS);\n        return false;\n      default:\n        throw new IllegalStateException(\n            String.format(\n                \"Cannot process unknown snapshot operation: %s (snapshot id %s)\",\n                op.toLowerCase(Locale.ROOT), snapshot.snapshotId()));\n    }\n  }\n\n  /**\n   * Get the next snapshot skipping over rewrite and delete snapshots. Async must handle nulls.\n   *\n   * @param curSnapshot the current snapshot\n   * @return the next valid snapshot (not a rewrite or delete snapshot), returns null if all\n   *     remaining snapshots should be skipped.\n   */\n  protected Snapshot nextValidSnapshot(Snapshot curSnapshot) {\n    Snapshot nextSnapshot;\n    // if there were no valid snapshots, check for an initialOffset again\n    if (curSnapshot == null) {\n      StreamingOffset startingOffset =","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/source/BaseSparkMicroBatchPlanner.java#L58-L94","documentation":"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.","triggerScenarios":"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.","commonSituations":"Mixed Iceberg versions: writer cluster newer than reader; manually crafted snapshots via API; snapshots produced by third-party engines using unusual operations.","solutions":["Upgrade the reader's Iceberg runtime to at least the version used by the writer.","Identify the snapshot id from the message and inspect its operation via table.snapshots().","If a custom writer produced the snapshot, switch it to standard operations (append/replace/overwrite/delete).","As a workaround, expire the offending snapshot so streaming continues from a valid one."],"exampleFix":"// before\n// reader Iceberg 1.4 encounters op from Iceberg 1.7\n// after\n// upgrade dependency\nimplementation 'org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.7.0'","handlingStrategy":"validation","validationCode":"// check snapshot operation before relying on the stream\nfor (Snapshot s : table.snapshots()) {\n  String op = s.operation();\n  if (!Set.of(\"append\",\"delete\",\"overwrite\",\"replace\").contains(op)) {\n    throw new IllegalStateException(\"unsupported op: \" + op);\n  }\n}","typeGuard":null,"tryCatchPattern":"try { batch = plan(); } catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"unknown snapshot operation\")) upgradeRuntimeAndRestart();\n  else throw e;\n}","preventionTips":["Pin one Iceberg version across writer and reader clusters.","Inspect snapshot operations when adopting new writers.","Expire non-standard snapshots before enabling streaming."],"tags":["spark","streaming","snapshot","forward-compatibility"],"backgroundTag":"invalid-enum-value","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}