apache/iceberg · error · java.lang.UnsupportedOperationException
Unsupported ZonedTimestampType.
Error message
Unsupported ZonedTimestampType.
What it means
FlinkTypeVisitor is the abstract visitor mapping Flink logical types to Iceberg types; it provides a default visit(ZonedTimestampType) that throws UnsupportedOperationException because TIMESTAMP WITH LOCAL TIME ZONE has no direct Iceberg mapping in this conversion path. Subclasses may override, but by default encountering this type aborts the conversion.
Source
Thrown at flink/v2.1/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.");
}
@OverrideView on GitHub (pinned to 86d9c8fc54)
Solutions
- Cast the column to TIMESTAMP (without local time zone) before writing to Iceberg.
- Override visit(ZonedTimestampType) in a custom visitor if a specific mapping is needed.
- Express the value as TIMESTAMP and store the timezone semantics out-of-band.
Example fix
// before CREATE TABLE t (ts TIMESTAMP(3) WITH LOCAL TIME ZONE) -- iceberg sink // after CREATE TABLE t (ts TIMESTAMP(3)) -- cast: CAST(ts AS TIMESTAMP(3))
Defensive patterns
Strategy: validation
Validate before calling
schema.getColumns().forEach(c -> {
if (c.getDataType().getLogicalType() instanceof ZonedTimestampType) {
throw new IllegalArgumentException("Cast TIMESTAMP WITH LOCAL TIME ZONE before Iceberg write: " + c.getName());
}
}); Type guard
boolean isZonedTimestamp(LogicalType t) { return t instanceof ZonedTimestampType; } Try / catch
try {
RowType rowType = FlinkSchemaUtil.toType(rowDataType);
} catch (UnsupportedOperationException e) {
// inspect schema for TIMESTAMP_LTZ columns and cast them
} Prevention
- Avoid TIMESTAMP WITH LOCAL TIME ZONE columns in tables written to Iceberg.
- Cast to TIMESTAMP(6) at the source query boundary.
- Check connector-inferred schemas for TIMESTAMP_LTZ before registering Iceberg sinks.
When it happens
Trigger: Any Flink-to-Iceberg type conversion (e.g. FlinkSchemaUtil.toType / fromFlinkSchema) traversing a field of type TIMESTAMP(3) WITH LOCAL TIME ZONE (ZonedTimestampType) using the default visitor behavior.
Common situations: Tables with columns sourced from CDC/other connectors using TIMESTAMP_LTZ; writing such a schema into Iceberg without first casting to TIMESTAMP.
Related errors
- Unsupported YearMonthIntervalType.
- Unsupported DayTimeIntervalType.
- Unsupported DistinctType.
- Unsupported StructuredType.
- Unsupported type: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f8cf6c074ceef7c3.
Report an issue: GitHub.