apache/iceberg · error · UnsupportedOperationException

Cannot apply unknown table change:

Error message

Cannot apply unknown table change: 

What it means

FlinkAlterTableUtil.applySchemaChanges converts Flink TableChange objects into Iceberg UpdateSchema operations. When it encounters a TableChange subtype it has no mapping for, it throws UnsupportedOperationException. This guards against silently ignoring schema changes that Iceberg cannot represent.

Solutions

  1. Avoid DDL that produces the unsupported change type (e.g. do not DROP constraints; instead use UPDATE on identifier fields via a fresh UpdateSchema).
  2. Check supported change types in FlinkAlterTableUtil.applySchemaChanges and use an equivalent supported change.
  3. Set identifier fields directly with table.updateSchema().setIdentifierFields(...) instead of constraint-based DDL.
  4. Upgrade Iceberg to a version that supports the change type.

Example fix

// before
ALTER TABLE iceberg_table DROP CONSTRAINT pk;
// after
-- not supported via Flink DDL; use:
Table table = ...; table.updateSchema().setIdentifierFields("id").commit();
Defensive patterns

Strategy: try-catch

Validate before calling

// java
boolean supported = changes.stream().allMatch(c ->
    c instanceof TableChange.AddColumn || c instanceof TableChange.DeleteColumn
    || c instanceof TableChange.ModifyColumn || c instanceof TableChange.ModifyUniqueConstraint);
if (!supported) { throw new IllegalArgumentException("change type not supported by Iceberg Flink catalog"); }

Type guard

boolean isSupportedChange(TableChange c) {
  return c instanceof TableChange.AddColumn
      || c instanceof TableChange.DeleteColumn
      || c instanceof TableChange.ModifyColumn
      || c instanceof TableChange.ModifyUniqueConstraint;
}

Try / catch

try {
  FlinkAlterTableUtil.applySchemaChanges(update, changes);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().startsWith("Cannot apply unknown table change")) {
    // fall back to direct UpdateSchema API
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling ALTER TABLE with a change type not handled by the instanceof chain in applySchemaChanges (e.g. DropConstraint or a new Flink TableChange subtype added in a newer Flink version).

Common situations: Running `ALTER TABLE t DROP CONSTRAINT` or constraint-manipulation DDL through the Flink Iceberg catalog; using a Flink SQL feature whose change type predates Iceberg's support; upgrading Flink and relying on newly added TableChange subtypes.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/cd7c21ba6b24e21b. Report an issue: GitHub.

Appendix: source

Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/util/FlinkAlterTableUtil.java:149

      } else if (change instanceof TableChange.DropColumn) {
        TableChange.DropColumn dropColumn = (TableChange.DropColumn) change;
        pendingUpdate.deleteColumn(dropColumn.getColumnName());
      } else if (change instanceof TableChange.AddWatermark) {
        throw new UnsupportedOperationException("Unsupported table change: AddWatermark.");
      } else if (change instanceof TableChange.ModifyWatermark) {
        throw new UnsupportedOperationException("Unsupported table change: ModifyWatermark.");
      } else if (change instanceof TableChange.DropWatermark) {
        throw new UnsupportedOperationException("Unsupported table change: DropWatermark.");
      } else if (change instanceof TableChange.AddUniqueConstraint) {
        TableChange.AddUniqueConstraint addPk = (TableChange.AddUniqueConstraint) change;
        applyUniqueConstraint(pendingUpdate, addPk.getConstraint());
      } else if (change instanceof TableChange.ModifyUniqueConstraint) {
        TableChange.ModifyUniqueConstraint modifyPk = (TableChange.ModifyUniqueConstraint) change;
        applyUniqueConstraint(pendingUpdate, modifyPk.getNewConstraint());
      } else if (change instanceof TableChange.DropConstraint) {
        throw new UnsupportedOperationException("Unsupported table change: DropConstraint.");
      } else {
        throw new UnsupportedOperationException("Cannot apply unknown table change: " + change);
      }
    }
  }

  private static void applyAddColumn(UpdateSchema pendingUpdate, TableChange.AddColumn addColumn) {
    Column flinkColumn = addColumn.getColumn();
    Preconditions.checkArgument(
        FlinkCompatibilityUtil.isPhysicalColumn(flinkColumn),
        "Unsupported table change: Adding computed column %s.",
        flinkColumn.getName());

    Type icebergType = FlinkSchemaUtil.convert(flinkColumn.getDataType().getLogicalType());

    if (flinkColumn.getDataType().getLogicalType().isNullable()) {
      pendingUpdate.addColumn(
          flinkColumn.getName(), icebergType, flinkColumn.getComment().orElse(null));
    } else {
      pendingUpdate.addRequiredColumn(

View on GitHub (pinned to 86d9c8fc54)