apache/iceberg · error · UnsupportedOperationException

Struct type is not supported

Error message

Struct type is not supported

What it means

GenericArrowVectorAccessorFactory registers throwing Suppliers for struct and list logical types, so requesting an accessor for a STRUCT column yields a Supplier that throws this UnsupportedOperationException when invoked. The arrow accessor factory simply does not support struct columns in vectorized reads.

Source

Thrown at arrow/src/main/java/org/apache/iceberg/arrow/vectorized/ArrowVectorAccessors.java:44

import org.apache.iceberg.arrow.vectorized.GenericArrowVectorAccessorFactory.DecimalFactory;
import org.apache.iceberg.arrow.vectorized.GenericArrowVectorAccessorFactory.StringFactory;

final class ArrowVectorAccessors {

  private static final GenericArrowVectorAccessorFactory<?, String, ?, ?> FACTORY;

  static {
    FACTORY =
        new GenericArrowVectorAccessorFactory<>(
            JavaDecimalFactory::new,
            JavaStringFactory::new,
            throwingSupplier("Struct type is not supported"),
            throwingSupplier("List type is not supported"));
  }

  private static <T> Supplier<T> throwingSupplier(String message) {
    return () -> {
      throw new UnsupportedOperationException(message);
    };
  }

  private ArrowVectorAccessors() {
    throw new UnsupportedOperationException(
        ArrowVectorAccessors.class.getName() + " cannot be instantiated.");
  }

  static ArrowVectorAccessor<?, String, ?, ?> getVectorAccessor(VectorHolder holder) {
    return FACTORY.getVectorAccessor(holder);
  }

  private static final class JavaStringFactory implements StringFactory<String> {
    @Override
    public Class<String> getGenericClass() {
      return String.class;
    }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Exclude struct columns from the vectorized read projection, or read those columns via the non-vectorized path
  2. Flatten the struct fields into top-level columns in the query/schema
  3. Check the Iceberg type of each column before requesting an Arrow accessor and route unsupported types elsewhere

Example fix

// before
ArrowVectorAccessor a = getVectorAccessor(structHolder); // supplier throws
// after
if (structHolder.type().typeId() == TypeID.STRUCT) {
  // use row-based reader for this column
} else {
  ArrowVectorAccessor a = getVectorAccessor(structHolder);
}
Defensive patterns

Strategy: fallback

Validate before calling

if (holder Iceberg type is STRUCT) { routeColumnToRowReader(holder); }

Type guard

boolean isStruct(Type t) { return t.typeId() == TypeID.STRUCT; }

Try / catch

Supplier<Accessor> s = factory.get(structHolder); try { a = s.get(); } catch (UnsupportedOperationException e) { a = rowReaderAccessor(holder); }

Prevention

When it happens

Trigger: Reading a table whose schema contains a STRUCT column through the vectorized (Arrow) read path and invoking the accessor factory's struct supplier; passing a VectorHolder backed by a struct type into getVectorAccessor's factory map.

Common situations: Enabling vectorized reads on tables with nested struct fields; listing/reading a nested column set where a struct column sneaks into the batch projection.

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/94316c23403c86ce. Report an issue: GitHub.