apache/iceberg · error · UnsupportedOperationException

Not implemented for variant

Error message

Not implemented for variant

What it means

TypeWithSchemaVisitor is the base visitor used when traversing a Parquet schema alongside an Iceberg type; each method has a default null-returning or throwing body. The variant() method's default throws UnsupportedOperationException, so any traversal that encounters a Parquet variant group without a visitor override fails.

Source

Thrown at parquet/src/main/java/org/apache/iceberg/parquet/TypeWithSchemaVisitor.java:242

  public T message(Types.StructType iStruct, MessageType message, List<T> fields) {
    return null;
  }

  public T struct(Types.StructType iStruct, GroupType struct, List<T> fields) {
    return null;
  }

  public T list(Types.ListType iList, GroupType array, T element) {
    return null;
  }

  public T map(Types.MapType iMap, GroupType map, T key, T value) {
    return null;
  }

  public T variant(Types.VariantType iVariant, GroupType variant, T result) {
    throw new UnsupportedOperationException("Not implemented for variant");
  }

  public T primitive(
      org.apache.iceberg.types.Type.PrimitiveType iPrimitive, PrimitiveType primitive) {
    return null;
  }

  public ParquetVariantVisitor<T> variantVisitor() {
    return null;
  }

  protected String[] currentPath() {
    return Lists.newArrayList(fieldNames.descendingIterator()).toArray(new String[0]);
  }

  protected String[] path(String name) {
    List<String> list = Lists.newArrayList(fieldNames.descendingIterator());
    list.add(name);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Override variant(Types.VariantType, GroupType, T) in your TypeWithSchemaVisitor subclass with the appropriate handling.
  2. Use a built-in visitor from the same Iceberg version that already supports Variant.
  3. Upgrade iceberg-parquet so the pipeline's visitors handle variant columns.

Example fix

// before
class MyVisitor<T> extends TypeWithSchemaVisitor<T> { /* no variant() override */ }
// after
class MyVisitor<T> extends TypeWithSchemaVisitor<T> {
  @Override
  public T variant(Types.VariantType iVariant, GroupType variant, T result) {
    return visitGroup(variant); // handle variant fields
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean visitorSupportsVariant(TypeWithSchemaVisitor<?> v) {
  try {
    java.lang.reflect.Method m = v.getClass().getMethod("variant",
        Types.VariantType.class, GroupType.class, Object.class);
    return m.getDeclaringClass() != TypeWithSchemaVisitor.class;
  } catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
  result = TypeWithSchemaVisitor.visit(schema, parquetSchema, visitor);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().contains("variant")) {
    throw new IllegalArgumentException("Visitor does not support Variant columns; upgrade or override variant()", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling TypeWithSchemaVisitor.visitVariant (or a schema visit that encounters a variant-typed group) with a visitor subclass that does not override variant().

Common situations: Reading/writing tables containing Variant columns with a custom visitor (e.g. a type-to-Type converter, projection pruner) that predates Variant support; copying visitor code from older Iceberg versions.

Related errors


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