apache/iceberg · error · UnsupportedOperationException
Unsupported value for VARIANT in StructInternalRow:
Error message
Unsupported value for VARIANT in StructInternalRow:
What it means
toVariantVal converts stored variant values into Spark VariantVal, but only accepts Iceberg Variant instances; anything else throws UnsupportedOperationException naming the value's class. This guards the variant decoding path against unexpected internal representations.
Solutions
- Ensure reader and writer Iceberg versions are compatible for variant columns
- Wrap raw variant bytes into an Iceberg Variant before exposing them through the row
- Upgrade to a version where variant materialization is fixed
Example fix
// before: setting raw bytes into a variant column row.set(ordinal, variantBytes); // after row.set(ordinal, Variant.tryFrom(variantBytes));
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(value instanceof Variant)) {
throw new IllegalArgumentException("VARIANT column value must be an Iceberg Variant: " + value.getClass());
} Type guard
static boolean isVariantValue(Object v) {
return v instanceof org.apache.iceberg.variants.Variant;
} Try / catch
try {
VariantVal vv = row.getVariant(ordinal);
} catch (UnsupportedOperationException e) {
log.error("Variant materialization failed: {}", e.getMessage());
} Prevention
- Align Iceberg versions across writer and reader for variant columns
- Don't inject raw bytes into variant fields via custom code paths
- Add round-trip tests for variant columns
When it happens
Trigger: Reading a VARIANT column where the value object stored in the row is not an org.apache.iceberg.variants.Variant (e.g. raw byte[], ByteBuffer, or another wrapper) in StructInternalRow.
Common situations: Version skew between writer and reader internal variant representations; custom readers that put non-Variant objects into variant fields; bug in value materialization for variant columns.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Not implemented for variant
- Not implemented for variant
- Not implemented for variant
- Not implemented for variant
- Not implemented for variant
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/df2e36d096648a11.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:411
throw new UnsupportedOperationException("Unsupported BinaryView type: " + type);
}
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)