apache/iceberg · error · UnsupportedOperationException
Variants must be read using read(VariantMetadata)
Error message
Variants must be read using read(VariantMetadata)
What it means
VariantValueReader extends ParquetValueReader but Variants are not read in the normal read(reuse) style. The default read(VariantValue reuse) method deliberately throws UnsupportedOperationException because variant values require VariantMetadata context; callers must use read(VariantMetadata) instead.
Solutions
- Use read(VariantMetadata metadata) and supply the variant metadata obtained from the table/manifest
- Ensure the generic reader path dispatches to VariantValueReader specially instead of calling read(reuse)
- Upgrade or patch the consuming engine integration to support variants
Example fix
// before: generic read VariantValue v = variantReader.read(null); // after: provide metadata VariantValue v = variantReader.read(variantMetadata);
Defensive patterns
Strategy: type-guard
Validate before calling
if (reader instanceof ParquetVariantReaders.VariantValueReader) {
// must call read(VariantMetadata), not read(reuse)
} Type guard
VariantValue readVariant(ParquetValueReader<?> reader, VariantMetadata md) {
if (reader instanceof ParquetVariantReaders.VariantValueReader) {
return ((ParquetVariantReaders.VariantValueReader) reader).read(md);
}
throw new IllegalArgumentException("Not a variant reader");
} Try / catch
try {
v = reader.read(reuse);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("Variants must be read using read(VariantMetadata)")) {
v = ((VariantValueReader) reader).read(variantMetadata);
} else throw e;
} Prevention
- Route variant columns through variant-aware reader paths
- Check instanceof VariantValueReader before generic read(reuse) calls
- Keep engine adapters updated for the variant spec
When it happens
Trigger: Invoking read(reuse) on any VariantValueReader — typically from generic Parquet reader code that treats the variant column like an ordinary primitive, or from copied reader pipelines that call the base interface method.
Common situations: Wiring a variant reader into a generic column-reader path that only knows ParquetValueReader.read(reuse); custom engine adapters calling the wrong overload; frameworks iterating readers polymorphically without variant support.
Related errors
- AlwaysFalse is a placeholder only
- AlwaysTrue is a placeholder only
- Avro writer does not support variant types
- Batch reading is not supported in non-vectorized reader
- Cannot evaluate
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/abc5cd1f207c4d72.
Report an issue: GitHub.
Appendix: source
Thrown at parquet/src/main/java/org/apache/iceberg/parquet/ParquetVariantReaders.java:49
import org.apache.iceberg.relocated.com.google.common.collect.Iterables;
import org.apache.iceberg.variants.PhysicalType;
import org.apache.iceberg.variants.ShreddedObject;
import org.apache.iceberg.variants.ValueArray;
import org.apache.iceberg.variants.Variant;
import org.apache.iceberg.variants.VariantMetadata;
import org.apache.iceberg.variants.VariantObject;
import org.apache.iceberg.variants.VariantValue;
import org.apache.iceberg.variants.Variants;
import org.apache.parquet.column.ColumnDescriptor;
import org.apache.parquet.column.page.PageReadStore;
public class ParquetVariantReaders {
private ParquetVariantReaders() {}
public interface VariantValueReader extends ParquetValueReader<VariantValue> {
@Override
default VariantValue read(VariantValue reuse) {
throw new UnsupportedOperationException("Variants must be read using read(VariantMetadata)");
}
/** Reads a variant value */
VariantValue read(VariantMetadata metadata);
}
private static final VariantValue MISSING = null;
@SuppressWarnings("unchecked")
public static ParquetValueReader<Variant> variant(
ParquetValueReader<?> metadata, ParquetValueReader<?> value) {
return new VariantReader(
(ParquetValueReader<VariantMetadata>) metadata, (VariantValueReader) value);
}
public static ParquetValueReader<VariantMetadata> metadata(ColumnDescriptor desc) {
return new VariantMetadataReader(desc);
}View on GitHub (pinned to 86d9c8fc54)