apache/iceberg · error · java.lang.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 Flink schemas that declare watermark specifications, because watermark strategies are stream-processing concepts with no representation in Iceberg table metadata. Any non-empty getWatermarkSpecs() triggers UnsupportedOperationException.

Source

Thrown at flink/v1.20/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 clause from the Iceberg table DDL.
  2. Declare watermarks in the Flink streaming job or a VIEW over the table, not in the Iceberg catalog table definition.
  3. Keep the watermark on the source-side table (e.g. Kafka connector table) and treat the Iceberg table as a plain sink.

Example fix

// before
CREATE TABLE t (ts TIMESTAMP(3), WATERMARK FOR ts AS ts - INTERVAL '5' SECOND) WITH (...);
// after
CREATE TABLE t (ts TIMESTAMP(3));
// declare watermark in a view or the source table
Defensive patterns

Strategy: validation

Validate before calling

if (!table.getUnresolvedSchema().getWatermarkSpecs().isEmpty()) {
  throw new IllegalArgumentException("Watermarks are not allowed in Iceberg table DDL");
}

Type guard

boolean hasNoWatermarks(org.apache.flink.table.api.Schema s) {
  return s.getWatermarkSpecs().isEmpty();
}

Try / catch

try { catalog.createTable(path, table); }
catch (UnsupportedOperationException e) { /* strip WATERMARK clause and retry */ }

Prevention

When it happens

Trigger: CREATE TABLE against an Iceberg catalog whose DDL includes `WATERMARK FOR rowtime_column AS watermark_strategy`; also hit via alterTable paths that call validateFlinkTable.

Common situations: Copying stream-table DDL (Kafka connector style with watermark clauses) to Iceberg; templates that append watermark declarations to time-attribute columns; developers conflating event-time handling with table schema.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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