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

  1. Remove the WATERMARK FOR clause from the Iceberg DDL.
  2. Declare the watermark in an intermediate Flink VIEW or in the source table, not on the Iceberg sink table.
  3. 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

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


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