apache/iceberg · error · java.lang.UnsupportedOperationException

Unsupported logical type: %s

Error message

Unsupported logical type: %s

What it means

FlinkParquetWriters.primitive() throws UnsupportedOperationException 'Unsupported logical type: <originalType>' when a Parquet column carries a logical type annotation (OriginalType) that LogicalTypeWriterBuilder explicitly rejects (visitor returned empty), e.g. an unusual annotation like MAP keys or interval types not supported by the Flink writer.

Source

Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/data/FlinkParquetWriters.java:193

    }

    private ParquetValueWriter<?> newOption(Type fieldType, ParquetValueWriter<?> writer) {
      int maxD = type.getMaxDefinitionLevel(path(fieldType.getName()));
      return ParquetValueWriters.option(fieldType, maxD, writer);
    }

    @Override
    public ParquetValueWriter<?> primitive(LogicalType fType, PrimitiveType primitive) {
      ColumnDescriptor desc = type.getColumnDescription(currentPath());

      LogicalTypeAnnotation annotation = primitive.getLogicalTypeAnnotation();
      if (annotation != null) {
        Optional<ParquetValueWriter<?>> writer =
            annotation.accept(new LogicalTypeWriterBuilder(fType, desc));
        if (writer.isPresent()) {
          return writer.get();
        } else {
          throw new UnsupportedOperationException(
              "Unsupported logical type: " + primitive.getOriginalType());
        }
      }

      switch (primitive.getPrimitiveTypeName()) {
        case FIXED_LEN_BYTE_ARRAY:
        case BINARY:
          return byteArrays(desc);
        case BOOLEAN:
          return ParquetValueWriters.booleans(desc);
        case INT32:
          return ints(fType, desc);
        case INT64:
          return ParquetValueWriters.longs(desc);
        case FLOAT:
          return ParquetValueWriters.floats(desc);
        case DOUBLE:
          return ParquetValueWriters.doubles(desc);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check the annotation in the message and retype the column to a supported Iceberg type (e.g. string instead of enum/json annotation).
  2. Write with a different file format (ORC/Avro) that handles the type.
  3. Upgrade iceberg-flink for potentially broader annotation support.
  4. Transform the data pipeline to drop/convert the unsupported column.

Example fix

// before
Types.NestedField.of(1, false, "status", Types.StringType.get()) // mapped with ENUM annotation
// after
// ensure the parquet type carries no unsupported annotation (plain STRING)
Defensive patterns

Strategy: validation

Validate before calling

// ensure columns map to supported parquet logical annotations
schema.columns().forEach(c -> {
  if (c.type() instanceof Types.StringType || c.type() instanceof Types.BinaryType) {
    // plain STRING / BINARY annotations are supported; avoid ENUM/JSON/INTERVAL
  }
});

Try / catch

try {
  writer.write(row);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().startsWith("Unsupported logical type")) {
    throw new IllegalStateException("Retype column or switch format: " + e.getMessage());
  }
  throw e;
}

Prevention

When it happens

Trigger: Writing Parquet files where a primitive's Parquet logical type annotation is not accepted by the LogicalTypeWriterBuilder visitor (annotation present but no writer produced).

Common situations: Columns with exotic parquet annotations (e.g. ENUM, JSON, INTERVAL) mapped from Iceberg types; version drift between parquet-columnar and iceberg-flink.

Related errors


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