{"record":{"id":"ab1f0dcd8a3b213e","repo":"apache/iceberg","slug":"cannot-apply-unknown-table-change-change-ab1f0d","errorCode":null,"errorMessage":"Cannot apply unknown table change: ${change}","messagePattern":"Cannot apply unknown table change: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java","lineNumber":155,"sourceCode":"   * Applies a list of Spark table changes to an {@link UpdateProperties} operation.\n   *\n   * @param pendingUpdate an uncommitted UpdateProperties operation to configure\n   * @param changes a list of Spark table changes\n   * @return the UpdateProperties operation configured with the changes\n   */\n  public static UpdateProperties applyPropertyChanges(\n      UpdateProperties pendingUpdate, List<TableChange> changes) {\n    for (TableChange change : changes) {\n      if (change instanceof TableChange.SetProperty) {\n        TableChange.SetProperty set = (TableChange.SetProperty) change;\n        pendingUpdate.set(set.property(), set.value());\n\n      } else if (change instanceof TableChange.RemoveProperty) {\n        TableChange.RemoveProperty remove = (TableChange.RemoveProperty) change;\n        pendingUpdate.remove(remove.property());\n\n      } else {\n        throw new UnsupportedOperationException(\"Cannot apply unknown table change: \" + change);\n      }\n    }\n\n    return pendingUpdate;\n  }\n\n  /**\n   * Applies a list of Spark table changes to an {@link UpdateSchema} operation.\n   *\n   * @param pendingUpdate an uncommitted UpdateSchema operation to configure\n   * @param changes a list of Spark table changes\n   * @return the UpdateSchema operation configured with the changes\n   */\n  public static UpdateSchema applySchemaChanges(\n      UpdateSchema pendingUpdate, List<TableChange> changes) {\n    for (TableChange change : changes) {\n      if (change instanceof TableChange.AddColumn) {\n        apply(pendingUpdate, (TableChange.AddColumn) change);","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java#L137-L173","documentation":"applyPropertyChanges iterates Spark TableChange instances and forwards supported ones (SetProperty, RemoveProperty) to an Iceberg PendingUpdate. Any other TableChange subtype is rejected with UnsupportedOperationException because table-property updates cannot express it.","triggerScenarios":"ALTER TABLE ... SET TBLPROPERTIES / UNSET TBLPROPERTIES path receiving a TableChange other than SetProperty or RemoveProperty, e.g. an engine or framework submitting column/comment changes through the property-change application path.","commonSituations":"Framework code that batches arbitrary TableChange arrays and calls applyPropertyChanges for all of them instead of routing schema changes to applySchemaChanges.","solutions":["Route non-property changes (AddColumn, UpdateColumnType, etc.) to Spark3Util.applySchemaChanges instead","Filter the change list so only SetProperty/RemoveProperty reach applyPropertyChanges","Check the Iceberg/Spark version — newer versions support more change types"],"exampleFix":"// before\nSpark3Util.applyPropertyChanges(table, changes); // changes include UpdateColumnComment\n// after\nList<TableChange> props = changes.stream().filter(c -> c instanceof TableChange.SetProperty || c instanceof TableChange.RemoveProperty).collect(toList());\nSpark3Util.applyPropertyChanges(table, props);","handlingStrategy":"type-guard","validationCode":"List<TableChange> props = changes.stream().filter(c -> c instanceof TableChange.SetProperty || c instanceof TableChange.RemoveProperty).collect(Collectors.toList());\nif (props.size() != changes.size()) throw new IllegalArgumentException(\"non-property changes must go through applySchemaChanges\");","typeGuard":"boolean isPropertyChange(TableChange c) { return c instanceof TableChange.SetProperty || c instanceof TableChange.RemoveProperty; }","tryCatchPattern":"try { Spark3Util.applyPropertyChanges(table, changes); } catch (UnsupportedOperationException e) { if (e.getMessage().contains(\"Cannot apply unknown table change\")) { /* split changes by type and route */ } else throw e; }","preventionTips":["Partition change lists: property changes -> applyPropertyChanges, schema changes -> applySchemaChanges","Never pass a mixed change array to either helper","Log unknown change types during upgrades to new Spark versions"],"tags":["spark","table-change","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}