apache/iceberg · error · UnsupportedOperationException
Unsupported value for VARIANT in StructInternalRow: ${value.
Error message
Unsupported value for VARIANT in StructInternalRow: ${value.getClass()} What it means
toVariantVal converts a VARIANT column's in-memory value into Spark's VariantVal, accepting Iceberg Variant instances (and null). Any other Java class triggers an UnsupportedOperationException naming the unexpected class — the stored representation does not match what the Iceberg variant machinery produces.
Source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:374
throw new UnsupportedOperationException("Unsupported array element type: " + elementType);
}
}
private static VariantVal toVariantVal(Object value) {
if (value instanceof Variant) {
Variant variant = (Variant) value;
byte[] metadataBytes = new byte[variant.metadata().sizeInBytes()];
ByteBuffer metadataBuffer = ByteBuffer.wrap(metadataBytes).order(ByteOrder.LITTLE_ENDIAN);
variant.metadata().writeTo(metadataBuffer, 0);
byte[] valueBytes = new byte[variant.value().sizeInBytes()];
ByteBuffer valueBuffer = ByteBuffer.wrap(valueBytes).order(ByteOrder.LITTLE_ENDIAN);
variant.value().writeTo(valueBuffer, 0);
return new VariantVal(valueBytes, metadataBytes);
}
throw new UnsupportedOperationException(
"Unsupported value for VARIANT in StructInternalRow: " + value.getClass());
}
@SuppressWarnings("unchecked")
private <T> GenericArrayData fillArray(
Collection<?> values, Function<Object[], BiConsumer<Integer, T>> makeSetter) {
Object[] array = new Object[values.size()];
BiConsumer<Integer, T> setter = makeSetter.apply(array);
int index = 0;
for (Object value : values) {
if (value == null) {
array[index] = null;
} else {
setter.accept(index, (T) value);
}
index += 1;View on GitHub (pinned to 86d9c8fc54)
Solutions
- Fix the producer so VARIANT columns hold proper org.apache.iceberg.variant.Variant instances.
- Align the Iceberg reader runtime and producing writer versions for variant support.
- If values arrive as raw bytes, reconstruct the Variant from metadata+value buffers before inserting into the row.
- Use the class name in the message to locate which pipeline stage stored the wrong representation.
Example fix
// before row.set(ordinal, rawMetadataBytes); // wrong: byte[] stored in VARIANT column // after Variant variant = Variants.create(metadataBuffer, valueBuffer); row.set(ordinal, variant);
Defensive patterns
Strategy: type-guard
Validate before calling
Object v = row.get(ordinal);
if (v != null && !(v instanceof Variant)) {
throw new IllegalStateException("VARIANT column holds non-Variant: " + v.getClass());
} Type guard
static boolean isVariantValue(Object v) {
return v == null || v instanceof Variant;
} Try / catch
try {
VariantVal val = structRow.getVariant(ordinal);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("VARIANT")) {
// decode raw bytes into a Variant, then retry
} else throw e;
} Prevention
- Only insert org.apache.iceberg.variant.Variant instances into VARIANT columns.
- Align writer and reader Iceberg versions where variant support is involved.
- Unit-test variant round-trips through StructInternalRow in custom integrations.
When it happens
Trigger: Calling getVariant(ordinal) or converting an array of variants on a StructInternalRow where the VARIANT column's value is neither a Variant nor null — e.g. a custom integration stored raw byte[]/String in a variant column, or mixed Iceberg versions deserialized variants differently.
Common situations: Third-party writers putting non-Variant objects into variant columns; writer/reader Iceberg version mismatch around variant materialization; custom data-source integrations bypassing variant encoding.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unknown type for int field. Type name: + integer.getClass().
- Unknown type for long field. Type name: + longVal.getClass()
- Unsupported value for VARIANT in StructInternalRow: " + valu
- Cannot parse type string: variant is not a primitive type
- Failed to read Variant %s of type %s as int
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ca9818df31d9d0bb.
Report an issue: GitHub.