apache/iceberg · error · UnsupportedOperationException

Not implemented for variant

Error message

Not implemented for variant

What it means

ParquetWithSparkSchemaVisitor is a schema visitor used when reading Parquet data with a Spark schema. Its default variant(...) method is a stub that throws UnsupportedOperationException — subclass/visitor implementations must override it to handle Iceberg variant columns in Parquet files.

Source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/data/ParquetWithSparkSchemaVisitor.java:236

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

  public T list(ArrayType sArray, GroupType array, T element) {
    return null;
  }

  public T map(MapType sMap, GroupType map, T key, T value) {
    return null;
  }

  public T primitive(DataType sPrimitive, PrimitiveType primitive) {
    return null;
  }

  public T variant(VariantType sVariant, GroupType variant) {
    throw new UnsupportedOperationException("Not implemented for variant");
  }

  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);
    return list.toArray(new String[0]);
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Upgrade Iceberg to a version where the reader used supports variant columns
  2. Implement/override the variant() method in your visitor subclass
  3. Avoid reading variant columns through this reader path (exclude them from the projection)
  4. Convert variant columns to string/json for engines or code paths without variant support

Example fix

// before
new ParquetWithSparkSchemaVisitor<T>() { public T primitive(DataType s, PrimitiveType p) {...} }
// after
new ParquetWithSparkSchemaVisitor<T>() {
  @Override public T variant(VariantType sv, GroupType g) { return variantReader(g); }
  public T primitive(DataType s, PrimitiveType p) {...}
}
Defensive patterns

Strategy: type-guard

Validate before calling

Schema schema = table.schema();
boolean hasVariant = schema.columns().stream()
    .anyMatch(c -> c.type().typeId() == Type.TypeID.VARIANT);
if (hasVariant) { /* use a variant-capable reader or override variant() */ }

Type guard

boolean readerSupportsVariant(ParquetWithSparkSchemaVisitor<?> v) {
  try { v.getClass().getMethod("variant", VariantType.class, GroupType.class); return true; }
  catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
  ParquetIO.read(reader).call(visitor);
} catch (UnsupportedOperationException e) {
  if ("Not implemented for variant".equals(e.getMessage())) { /* switch to variant-capable reader */ }
  else throw e;
}

Prevention

When it happens

Trigger: Reading a Parquet file whose schema contains a variant (ShreddedVariant/VariantType) column using a visitor that does not override variant(), e.g. generic Parquet value readers path over a table with variant columns.

Common situations: Reading tables containing variant columns (Iceberg spec v3) with code paths that predate variant support; custom readers subclassing ParquetWithSparkSchemaVisitor without implementing variant().

Related errors


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