{"record":{"id":"01295e63273ae6a7","repo":"apache/iceberg","slug":"unsupported-table-change-dropconstraint-01295e","errorCode":null,"errorMessage":"Unsupported table change: DropConstraint.","messagePattern":"Unsupported table change: DropConstraint\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/util/FlinkAlterTableUtil.java","lineNumber":147,"sourceCode":"        TableChange.ModifyColumn modifyColumn = (TableChange.ModifyColumn) change;\n        applyModifyColumn(pendingUpdate, modifyColumn);\n      } else if (change instanceof TableChange.DropColumn) {\n        TableChange.DropColumn dropColumn = (TableChange.DropColumn) change;\n        pendingUpdate.deleteColumn(dropColumn.getColumnName());\n      } else if (change instanceof TableChange.AddWatermark) {\n        throw new UnsupportedOperationException(\"Unsupported table change: AddWatermark.\");\n      } else if (change instanceof TableChange.ModifyWatermark) {\n        throw new UnsupportedOperationException(\"Unsupported table change: ModifyWatermark.\");\n      } else if (change instanceof TableChange.DropWatermark) {\n        throw new UnsupportedOperationException(\"Unsupported table change: DropWatermark.\");\n      } else if (change instanceof TableChange.AddUniqueConstraint) {\n        TableChange.AddUniqueConstraint addPk = (TableChange.AddUniqueConstraint) change;\n        applyUniqueConstraint(pendingUpdate, addPk.getConstraint());\n      } else if (change instanceof TableChange.ModifyUniqueConstraint) {\n        TableChange.ModifyUniqueConstraint modifyPk = (TableChange.ModifyUniqueConstraint) change;\n        applyUniqueConstraint(pendingUpdate, modifyPk.getNewConstraint());\n      } else if (change instanceof TableChange.DropConstraint) {\n        throw new UnsupportedOperationException(\"Unsupported table change: DropConstraint.\");\n      } else {\n        throw new UnsupportedOperationException(\"Cannot apply unknown table change: \" + change);\n      }\n    }\n  }\n\n  private static void applyAddColumn(UpdateSchema pendingUpdate, TableChange.AddColumn addColumn) {\n    Column flinkColumn = addColumn.getColumn();\n    Preconditions.checkArgument(\n        FlinkCompatibilityUtil.isPhysicalColumn(flinkColumn),\n        \"Unsupported table change: Adding computed column %s.\",\n        flinkColumn.getName());\n\n    Type icebergType = FlinkSchemaUtil.convert(flinkColumn.getDataType().getLogicalType());\n\n    if (flinkColumn.getDataType().getLogicalType().isNullable()) {\n      pendingUpdate.addColumn(\n          flinkColumn.getName(), icebergType, flinkColumn.getComment().orElse(null));","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/util/FlinkAlterTableUtil.java#L129-L165","documentation":"Flink's SQL ALTER TABLE path in FlinkAlterTableUtil.applySchemaChanges does not support dropping a named constraint (primary key or unique key) from an Iceberg table. When a TableChange.DropConstraint arrives, the utility throws UnsupportedOperationException because UpdateSchema has no counterpart operation for removing identifier-field/constraint definitions. Dropping constraints must be done through other means (e.g. UpdateSchema.setIdentifierFields with no fields).","triggerScenarios":"Executing ALTER TABLE ... DROP PRIMARY KEY (or any DROP CONSTRAINT) against an Iceberg table via the Flink catalog, which routes the change into applySchemaChanges.","commonSituations":"Users migrating DDL from engines where constraint drops are routine (MySQL/Postgres/Spark) to Flink + Iceberg; schema evolution scripts that remove keys; framework-generated DDL that manages constraints declaratively.","solutions":["Avoid DROP CONSTRAINT DDL in Flink; instead use Table.updateSchema().setIdentifierFields() to redefine or clear identifier fields","Clear the primary key by setting identifier fields to an empty set via a custom catalog call or job instead of a SQL change","Handle UnsupportedOperationException in the Flink alter path and translate to a clear user-facing message that constraint drops are unsupported"],"exampleFix":"// before\nALTER TABLE iceberg_table DROP PRIMARY KEY;\n// after\nTable table = catalog.loadTable(tableIdentifier);\ntable.updateSchema().setIdentifierFields(ImmutableList.of()).commit();","handlingStrategy":"validation","validationCode":"boolean dropsConstraint = changes.stream().anyMatch(c -> c instanceof TableChange.DropConstraint);\nif (dropsConstraint) { throw new IllegalArgumentException(\"Constraint drops unsupported by Iceberg Flink catalog; use updateSchema().setIdentifierFields()\"); }","typeGuard":"boolean isDroppable = change instanceof TableChange.DropConstraint; // route separately\nif (isDroppable) { handleConstraintDropManually(table); return; }","tryCatchPattern":"try { FlinkAlterTableUtil.applySchemaChanges(update, changes); }\ncatch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"DropConstraint\")) { /* apply setIdentifierFields fallback */ }\n  else throw e;\n}","preventionTips":["Never emit DROP CONSTRAINT DDL against Iceberg tables in Flink","Manage identifier fields explicitly via Table.updateSchema()","Review migration scripts from other engines for constraint operations before running them on Iceberg"],"tags":["flink","iceberg","unsupported-operation","schema-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-14T11:17:12.474Z"}