apache/iceberg · error · java.lang.UnsupportedOperationException

Unsupported StructuredType.

Error message

Unsupported StructuredType.

What it means

Flink StructuredType is an anonymous structured/record logical type (e.g. from class-based UDTs) with no direct Iceberg mapping, so FlinkTypeVisitor throws UnsupportedOperationException when it is visited. Iceberg conversion expects concrete row types it can map to Iceberg StructType.

Source

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

  @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
  public T visit(StructuredType structuredType) {
    throw new UnsupportedOperationException("Unsupported StructuredType.");
  }

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

  @Override
  public T visit(RawType<?> rawType) {
    throw new UnsupportedOperationException("Unsupported RawType.");
  }

  @Override
  public T visit(SymbolType<?> symbolType) {
    throw new UnsupportedOperationException("Unsupported SymbolType.");
  }

  @Override

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Convert the UDT column to an explicit ROW(...) type, e.g. CAST(obj AS ROW<a INT, b STRING>), so Iceberg maps it to StructType.
  2. Flatten the structured column into individual scalar columns before the Iceberg sink.
  3. Remove the structured column from the Iceberg table schema if it is not needed.
  4. Override visit(StructuredType) in a custom FlinkTypeVisitor subclass to map fields to an Iceberg StructType.

Example fix

// before
INSERT INTO iceberg_t SELECT my_udt_col FROM src; // StructuredType
// after
INSERT INTO iceberg_t SELECT CAST(my_udt_col AS ROW<x INT, y STRING>) AS r FROM src;
Defensive patterns

Strategy: validation

Validate before calling

import org.apache.flink.table.types.logical.LogicalType;
import org.apache.flink.table.types.logical.StructuredType;

static boolean containsStructuredType(org.apache.flink.table.api.Schema schema) {
  return schema.getColumns().stream()
      .anyMatch(c -> c.getType().getLogicalType() instanceof StructuredType);
}

Type guard

static boolean isStructuredType(LogicalType t) {
  return t instanceof StructuredType;
}

Prevention

When it happens

Trigger: Converting a row type containing a StructuredType column, typically produced by Java/Scala class UDTs or connectors emitting structured logical types, when running FlinkTypeVisitor-based schema conversion.

Common situations: Sink queries that include UDT columns feeding Iceberg; Flink version differences where inference yields StructuredType where an older version inferred RowType; object constructors in SELECT lists producing structured types.

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/22aff1fbd2b9e45d. Report an issue: GitHub.