{"record":{"id":"4da0177e32991e94","repo":"apache/iceberg","slug":"cannot-apply-unknown-table-change-change-4da017","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/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java","lineNumber":336,"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":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java#L318-L354","documentation":"SparkCatalog.alterTable maps Spark UpdateTableStatement changes to Iceberg commit types (SetProperty, RemoveProperty, ColumnChange, plus special-cased location/snapshot changes). A change object of an unrecognized type cannot be applied, so it throws UnsupportedOperationException listing the change.","triggerScenarios":"Calling SparkCatalog.alterTable(Identifier, TableChange[]) with a TableChange implementation outside the handled set — typically a custom TableChange subclass or a Spark change type added in a newer Spark version than the bundled Iceberg SparkCatalog supports.","commonSituations":"Spark/Iceberg version mismatch introducing new change kinds (e.g. newer Spark option-change types); custom engine integrations crafting their own TableChange implementations; test code passing unsupported changes.","solutions":["Upgrade iceberg-spark to a version matching your Spark version so all change types are handled","Inspect the failing change's class and convert it to a supported change (SetProperty/RemoveProperty/ColumnChange)","Avoid custom TableChange subclasses; use Spark SQL statements that generate supported changes"],"exampleFix":"// before\nTableChange custom = new MyCustomChange();\ncatalog.alterTable(ident, custom); // throws\n// after\ncatalog.alterTable(ident, TableChange.setProperty(\"write.format.default\", \"parquet\"));","handlingStrategy":"validation","validationCode":"for (TableChange c : changes) { if (!(c instanceof SetProperty || c instanceof RemoveProperty || c instanceof ColumnChange)) { throw new IllegalArgumentException(\"Unsupported change: \" + c); } }","typeGuard":"boolean isSupportedChange(TableChange c) { return c instanceof SetProperty || c instanceof RemoveProperty || c instanceof ColumnChange; }","tryCatchPattern":"try { sparkCatalog.alterTable(ident, changes); } catch (UnsupportedOperationException e) { log.error(\"Unsupported table change, check iceberg-spark/Spark version alignment\", e); throw e; }","preventionTips":["Keep iceberg-spark version matched to your Spark version","Only use standard Spark SQL statements to generate TableChanges","Avoid custom TableChange subclasses"],"tags":["spark","table-changes","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-23T08:17:48.524Z"}