{"record":{"id":"681ae9b7acefef58","repo":"apache/iceberg","slug":"cannot-apply-unknown-table-change-change-681ae9","errorCode":null,"errorMessage":"Cannot apply unknown table change: <change>","messagePattern":"Cannot apply unknown table change: <change>","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java","lineNumber":308,"sourceCode":"        } else if (\"cherry-pick-snapshot-id\".equalsIgnoreCase(set.property())) {\n          pickSnapshotId = set;\n        } else if (\"sort-order\".equalsIgnoreCase(set.property())) {\n          throw new UnsupportedOperationException(\n              \"Cannot specify the 'sort-order' because it's a reserved table \"\n                  + \"property. Please use the command 'ALTER TABLE ... WRITE ORDERED BY' to specify write sort-orders.\");\n        } else if (\"identifier-fields\".equalsIgnoreCase(set.property())) {\n          throw new UnsupportedOperationException(\n              \"Cannot specify the 'identifier-fields' because it's a reserved table property. \"\n                  + \"Please use the command 'ALTER TABLE ... SET IDENTIFIER FIELDS' to specify identifier fields.\");\n        } else {\n          propertyChanges.add(set);\n        }\n      } else if (change instanceof RemoveProperty) {\n        propertyChanges.add(change);\n      } else if (change instanceof ColumnChange) {\n        schemaChanges.add(change);\n      } else {\n        throw new UnsupportedOperationException(\"Cannot apply unknown table change: \" + change);\n      }\n    }\n\n    try {\n      org.apache.iceberg.Table table = icebergCatalog.loadTable(buildIdentifier(ident));\n      commitChanges(\n          table, setLocation, setSnapshotId, pickSnapshotId, propertyChanges, schemaChanges);\n      return new SparkTable(table);\n    } catch (org.apache.iceberg.exceptions.NoSuchTableException e) {\n      throw new NoSuchTableException(ident);\n    }\n  }\n\n  @Override\n  public boolean dropTable(Identifier ident) {\n    return catalogDropTable(ident);\n  }\n","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java#L290-L326","documentation":"SparkCatalog.alterTable iterates the incoming Spark TableChange list and classifies each change (property, location, snapshot, column). If a change is not a recognized Iceberg-supported type, it throws UnsupportedOperationException because Iceberg cannot translate that change into a metadata commit.","triggerScenarios":"Calling ALTER TABLE via Spark with a TableChange subtype Iceberg does not support, e.g. Spark's RemoveProperty variant not matching, or engine/plugin-generated custom TableChange instances passed to catalog().alterTable().","commonSituations":"Custom catalogs/plugins injecting new TableChange subtypes; Spark version upgrades adding new change kinds Iceberg hasn't mapped yet; programmatic use of the Spark catalog API with hand-built TableChange objects.","solutions":["Check the change type you are passing is one Iceberg supports: SetProperty, RemoveProperty, LocationChange, SetSnapshotId, or ColumnChange subtypes","Upgrade to a newer Iceberg version that may support the change kind","Apply unsupported changes directly through the Iceberg API (table.updateSchema(), table.updateProperties()) instead of the Spark catalog"],"exampleFix":"// before\nspark.sql(\"ALTER TABLE t SET TBLPROPERTIES ...\") // with an unsupported change kind from a plugin\n// after\nTable table = sparkCatalog.icebergCatalog().loadTable(ident);\ntable.updateProperties().set(\"key\", \"value\").commit();","handlingStrategy":"validation","validationCode":"if (!(change instanceof SetProperty || change instanceof RemoveProperty || change instanceof ColumnChange || change instanceof LocationChange || change instanceof SetSnapshotId)) { throw new IllegalArgumentException(\"Unsupported change: \" + change); }","typeGuard":"boolean isSupported(TableChange c) { return c instanceof SetProperty || c instanceof RemoveProperty || c instanceof ColumnChange || c instanceof LocationChange || c instanceof SetSnapshotId; }","tryCatchPattern":null,"preventionTips":["Only construct TableChange instances from documented Iceberg-supported subtypes","Validate changes with a type filter before passing to alterTable","Keep Iceberg and Spark versions aligned so new TableChange kinds are mapped"],"tags":["spark","unsupported-operation","catalog"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}