{"record":{"id":"56d2b0a95bfdbc7c","repo":"apache/iceberg","slug":"cannot-apply-unknown-table-change-56d2b0","errorCode":null,"errorMessage":"Cannot apply unknown table change: ","messagePattern":"Cannot apply unknown table change: ","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java","lineNumber":357,"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, true /* refreshEagerly */);\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":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java#L339-L375","documentation":"SparkCatalog.alterTable categorizes each TableChange into property and schema changes; a change type outside SetProperty/RemoveProperty/ColumnChange cannot be applied to an Iceberg table and throws UnsupportedOperationException naming the change object.","triggerScenarios":"Passing an unsupported Spark TableChange subclass (neither a property nor a column change) into catalog.alterTable(ident, change) — e.g. custom TableChange implementations or Spark engine changes adding new change types not yet mapped.","commonSituations":"Calling the V2 catalog alterTable API programmatically with hand-built TableChange objects; Spark version skew where newer change types are passed to an older Iceberg Spark integration; custom CatalogPlugin wrappers injecting their own change types.","solutions":["Restrict alterTable calls to supported changes: SetProperty, RemoveProperty, and ColumnChange (AddColumn, UpdateColumnComment, etc.).","Align Spark and Iceberg versions so all engine TableChange types are recognized by the integration.","If a new Spark change type is needed, upgrade Iceberg or implement handling in a custom catalog subclass.","Log/print the change object named in the message to identify the unsupported type."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for (TableChange change : changes) {\n  if (!(change instanceof SetProperty || change instanceof RemoveProperty\n      || change instanceof ColumnChange)) {\n    throw new IllegalArgumentException(\"Unsupported change type: \" + change.getClass().getName());\n  }\n}","typeGuard":"boolean isSupportedChange(TableChange c) {\n  return c instanceof SetProperty || c instanceof RemoveProperty || c instanceof ColumnChange;\n}","tryCatchPattern":"try {\n  catalog.alterTable(ident, changes);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().startsWith(\"Cannot apply unknown table change\")) {\n    LOG.error(\"Unsupported TableChange: {}\", e.getMessage());\n  }\n  throw e;\n}","preventionTips":["Only build changes from SetProperty/RemoveProperty/ColumnChange subclasses.","Keep Spark and Iceberg versions aligned so new engine change types are handled.","Log the change object from the message to identify the culprit quickly.","Avoid passing through arbitrary TableChange arrays from other plugins."],"tags":["spark","iceberg","alter-table","unsupported-change"],"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"}