apache/iceberg · error · UnsupportedOperationException
Cannot apply unknown table change:
Error message
Cannot apply unknown table change:
What it means
The default branch of applySchemaChanges throws this when a TableChange instance is not one of the recognized change types (add/modify/rename/drop column, unique-constraint changes, etc.). It indicates an unknown or newly introduced Flink TableChange subtype reached an older/exhaustive switch that does not handle it.
Source
Thrown at flink/v2.2/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)
Solutions
- Upgrade iceberg-flink-runtime to a version matching your Flink version so all change types are handled
- Log and inspect the change's class name to identify the unhandled type
- Pre-filter the TableChange list and reject unsupported types before calling applySchemaChanges
Example fix
// before
UnsupportedOperationException: Cannot apply unknown table change: ...
// after
if (!(change instanceof TableChange.AddColumn
|| change instanceof TableChange.ModifyColumn)) {
throw new IllegalArgumentException("Unsupported change: " + change.getClass().getName());
} Defensive patterns
Strategy: type-guard
Validate before calling
Set<Class<?>> supported = Set.of(TableChange.AddColumn.class, TableChange.ModifyColumn.class, TableChange.RenameColumn.class, TableChange.DropColumn.class, TableChange.AddUniqueConstraint.class, TableChange.ModifyUniqueConstraint.class);
boolean ok = changes.stream().allMatch(c -> supported.contains(c.getClass()));
if (!ok) throw new IllegalArgumentException("Change list contains unsupported types"); Type guard
static boolean isKnownSchemaChange(TableChange c) {
return c instanceof TableChange.AddColumn || c instanceof TableChange.ModifyColumn
|| c instanceof TableChange.RenameColumn || c instanceof TableChange.DropColumn
|| c instanceof TableChange.ModifyColumnPosition || c instanceof TableChange.AddUniqueConstraint
|| c instanceof TableChange.ModifyUniqueConstraint;
} Try / catch
try { FlinkAlterTableUtil.applySchemaChanges(update, changes); }
catch (UnsupportedOperationException e) {
if (e.getMessage().startsWith("Cannot apply unknown table change")) { log.warn("Unhandled change type; upgrade runtime", e); }
throw e;
} Prevention
- Keep iceberg-flink-runtime and Flink versions aligned
- Pre-filter change lists before dispatching to schema-update utilities
- Pin exact versions rather than floating ranges
When it happens
Trigger: Passing a TableChange subtype not handled by FlinkAlterTableUtil (e.g. a change type added in a newer Flink version or a custom TableChange) into catalog.alterTable / applySchemaChanges.
Common situations: Flink/Iceberg version skew where the Flink planner emits new change types; custom catalog wrappers forwarding unfiltered change lists; typos in change handling code.
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
- Unsupported table change: DropConstraint.
- Failed to list partitions of table %s
- Unsupported YearMonthIntervalType.
- Unsupported DayTimeIntervalType.
- Unsupported DistinctType.
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/9e06642928e7fae4.
Report an issue: GitHub.