apache/iceberg · error · java.lang.UnsupportedOperationException

Unsupported ZonedTimestampType.

Error message

Unsupported ZonedTimestampType.

What it means

FlinkTypeVisitor deliberately rejects Flink SQL types that have no Iceberg mapping. A ZonedTimestampType (TIMESTAMP WITH LOCAL TIME ZONE) cannot be represented losslessly in Iceberg's timestamp types, so the visitor throws UnsupportedOperationException. This fires whenever any Flink-to-Iceberg type conversion encounters a zoned timestamp in the schema.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/FlinkTypeVisitor.java:38

import org.apache.flink.table.types.logical.DayTimeIntervalType;
import org.apache.flink.table.types.logical.DistinctType;
import org.apache.flink.table.types.logical.LogicalType;
import org.apache.flink.table.types.logical.LogicalTypeVisitor;
import org.apache.flink.table.types.logical.NullType;
import org.apache.flink.table.types.logical.RawType;
import org.apache.flink.table.types.logical.StructuredType;
import org.apache.flink.table.types.logical.SymbolType;
import org.apache.flink.table.types.logical.YearMonthIntervalType;
import org.apache.flink.table.types.logical.ZonedTimestampType;

public abstract class FlinkTypeVisitor<T> implements LogicalTypeVisitor<T> {

  // ------------------------- Unsupported types ------------------------------

  @Override
  public T visit(ZonedTimestampType zonedTimestampType) {
    throw new UnsupportedOperationException("Unsupported ZonedTimestampType.");
  }

  @Override
  public T visit(YearMonthIntervalType yearMonthIntervalType) {
    throw new UnsupportedOperationException("Unsupported YearMonthIntervalType.");
  }

  @Override
  public T visit(DayTimeIntervalType dayTimeIntervalType) {
    throw new UnsupportedOperationException("Unsupported DayTimeIntervalType.");
  }

  @Override
  public T visit(DistinctType distinctType) {
    throw new UnsupportedOperationException("Unsupported DistinctType.");
  }

  @Override

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Change the column to TIMESTAMP (without time zone) — store UTC-normalized values instead.
  2. If you need zoned semantics, convert values to UTC and keep a separate zone column, or use ToTimestamp/UDF conversions before writing.
  3. Check your Iceberg/Flink version — some later versions added limited support or clearer mapping guidance for TIMESTAMP_LTZ.

Example fix

// before
event_time TIMESTAMP(3) WITH LOCAL TIME ZONE
// after
event_time TIMESTAMP(3)  -- convert to UTC before writing
Defensive patterns

Strategy: type-guard

Validate before calling

for (RelDataTypeField f : rowType.getFieldList()) {
  if (f.getType().getSqlTypeName() == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE) {
    throw new IllegalArgumentException("TIMESTAMP WITH LOCAL TIME ZONE not supported by Iceberg: " + f.getName());
  }
}

Type guard

static boolean isIcebergCompatible(LogicalType t) {
  return !(t instanceof ZonedTimestampType) && !(t instanceof YearMonthIntervalType);
}

Try / catch

try {
  convertFlinkTypeToIceberg(type);
} catch (UnsupportedOperationException e) {
  LOG.error("Unsupported Flink type for Iceberg: {}", e.getMessage());
  throw e;
}

Prevention

When it happens

Trigger: Creating an Iceberg table from a Flink schema that contains TIMESTAMP(3) WITH LOCAL TIME ZONE columns; pushing a Flink DataStream/RowType with zoned timestamps through FlinkSchemaUtil/FlinkTypeUtil conversion.

Common situations: Using Flink's TIMESTAMP_LTZ type in a CREATE TABLE backed by Iceberg; reading CDC sources (e.g. Debezium) that produce TIMESTAMP_WITH_LOCAL_TIME_ZONE and trying to sink to Iceberg.

Related errors


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