apache/iceberg · error · UnsupportedOperationException
Unsupported table change: AddWatermark.
Error message
Unsupported table change: AddWatermark.
What it means
FlinkAlterTableUtil.applySchemaChanges maps Flink TableChange objects onto Iceberg UpdateSchema operations. Iceberg tables do not support watermarks, so an AddWatermark change is rejected with UnsupportedOperationException. The change is never applied and the ALTER fails.
Source
Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/util/FlinkAlterTableUtil.java:135
/**
* Applies a list of Flink table changes to an {@link UpdateSchema} operation.
*
* @param pendingUpdate an uncommitted UpdateSchema operation to configure
* @param schemaChanges a list of Flink table changes
*/
public static void applySchemaChanges(
UpdateSchema pendingUpdate, List<TableChange> schemaChanges) {
for (TableChange change : schemaChanges) {
if (change instanceof TableChange.AddColumn) {
applyAddColumn(pendingUpdate, (TableChange.AddColumn) change);
} else if (change instanceof TableChange.ModifyColumn) {
TableChange.ModifyColumn modifyColumn = (TableChange.ModifyColumn) change;
applyModifyColumn(pendingUpdate, modifyColumn);
} 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);
}
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Remove the ADD WATERMARK statement; express event-time logic in the Flink job's SELECT instead (watermark on the source/derived table view)
- Define the watermark on a Flink VIEW over the Iceberg table rather than on the Iceberg table itself
- Patch via custom catalog if watermark semantics are truly needed (not supported upstream)
Example fix
-- before ALTER TABLE iceberg_table ADD WATERMARK FOR rowtime AS rowtime - INTERVAL '5' SECOND; -- after CREATE VIEW v AS SELECT *, rowtime - INTERVAL '5' SECOND AS wm FROM iceberg_table; -- watermark on view/source
Defensive patterns
Strategy: try-catch
Validate before calling
// before ALTER
if (changes.stream().anyMatch(c -> c instanceof TableChange.AddWatermark)) {
throw new IllegalArgumentException("Watermark DDL is not supported on Iceberg tables");
} Type guard
boolean isWatermarkChange(TableChange c) { return c instanceof TableChange.AddWatermark || c instanceof TableChange.ModifyWatermark || c instanceof TableChange.DropWatermark; } Try / catch
try {
FlinkAlterTableUtil.applySchemaChanges(update, changes);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("AddWatermark")) { /* move watermark to a view or source */ }
throw e;
} Prevention
- Never issue watermark DDL on Iceberg tables; put watermarks on Flink views or sources
- Filter out watermark TableChange types before forwarding changes to the Iceberg catalog
- Document watermark limitations in team DDL guidelines
When it happens
Trigger: Executing a Flink SQL 'ALTER TABLE ... ADD WATERMARK' (or calling TableEnvironment/DynamicCatalog with a TableChange.AddWatermark) against a table backed by the Iceberg catalog.
Common situations: Porting SQL written for Flink's built-in connector tables (which support watermarks) to Iceberg tables.
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: ModifyWatermark.
- Unsupported table change: DropWatermark.
- Unsupported table change: DropConstraint.
- Cannot apply unknown table change: {change}
- Cannot apply unknown modify-column change: {modifyColumn}
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/898f642ad324b97c.
Report an issue: GitHub.