apache/iceberg · error · UnsupportedOperationException
Creating table with watermark specs is not supported yet.
Error message
Creating table with watermark specs is not supported yet.
What it means
FlinkCatalog.validateFlinkTable rejects table schemas that declare watermark specs, since Iceberg tables do not store Flink watermark definitions. If schema.getWatermarkSpecs() is non-empty, UnsupportedOperationException is thrown during createIcebergTable or alterTable.
Source
Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/FlinkCatalog.java:639
}
private static void validateFlinkTable(CatalogBaseTable table) {
Preconditions.checkArgument(
table instanceof CatalogTable, "The Table should be a CatalogTable.");
org.apache.flink.table.api.Schema schema = table.getUnresolvedSchema();
schema
.getColumns()
.forEach(
column -> {
if (!FlinkCompatibilityUtil.isPhysicalColumn(column)) {
throw new UnsupportedOperationException(
"Creating table with computed columns is not supported yet.");
}
});
if (!schema.getWatermarkSpecs().isEmpty()) {
throw new UnsupportedOperationException(
"Creating table with watermark specs is not supported yet.");
}
}
private static PartitionSpec toPartitionSpec(List<String> partitionKeys, Schema icebergSchema) {
PartitionSpec.Builder builder = PartitionSpec.builderFor(icebergSchema);
partitionKeys.forEach(builder::identity);
return builder.build();
}
private static List<String> toPartitionKeys(PartitionSpec spec, Schema icebergSchema) {
ImmutableList.Builder<String> partitionKeysBuilder = ImmutableList.builder();
for (PartitionField field : spec.fields()) {
if (field.transform().isIdentity()) {
partitionKeysBuilder.add(icebergSchema.findColumnName(field.sourceId()));
} else {
// Not created by Flink SQL.
// For compatibility with iceberg tables, return empty.View on GitHub (pinned to 86d9c8fc54)
Solutions
- Remove the WATERMARK FOR clause from the Iceberg DDL.
- Declare the watermark in an intermediate Flink VIEW or in the source table, not on the Iceberg sink table.
- Apply watermark logic in the job's Table API (via `.watermark()` on the source) rather than the catalog DDL.
Example fix
// before
CREATE TABLE t (ts TIMESTAMP(3), WATERMARK FOR ts AS ts - INTERVAL '5' SECOND) WITH ('connector'='iceberg');
// after
CREATE TABLE t (ts TIMESTAMP(3)) WITH ('connector'='iceberg'); Defensive patterns
Strategy: validation
Validate before calling
// reject watermark specs before CREATE TABLE
if (!ddlSchema.getWatermarkSpecs().isEmpty()) {
// remove WATERMARK clauses; define them on the source/view instead
} Try / catch
try {
catalog.createTable(tablePath, table, false);
} catch (UnsupportedOperationException e) {
// strip watermark specs and retry
} Prevention
- Never copy WATERMARK clauses from streaming-source DDL into Iceberg sink DDL
- Define watermarks on source tables or in the job graph
- Lint Iceberg DDL for the WATERMARK FOR keyword
When it happens
Trigger: CREATE TABLE ... (`ts TIMESTAMP(3)`, WATERMARK FOR ts AS ts - INTERVAL '5' SECOND) with the iceberg connector; CREATE TABLE LIKE from a table with a WATERMARK; altering a table whose new schema contains watermark specs.
Common situations: Copying streaming source DDL (Kafka with event-time watermark) verbatim to an Iceberg sink; scaffolding generated by tools that include watermark clauses.
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: AddWatermark.
- Unsupported table change: ModifyWatermark.
- Unsupported table change: DropWatermark.
- Unsupported table change: AddWatermark.
- Unsupported table change: ModifyWatermark.
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/51286bf9067575ae.
Report an issue: GitHub.