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

  1. Ensure reader and writer Iceberg versions are compatible for variant columns
  2. Wrap raw variant bytes into an Iceberg Variant before exposing them through the row
  3. 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

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


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)