apache/iceberg · error · UnsupportedOperationException

Unsupported value for VARIANT in StructInternalRow: " + valu

Error message

Unsupported value for VARIANT in StructInternalRow: " + value.getClass()

What it means

toVariantVal converts Iceberg Variant values into Spark VariantVal. It only handles org.apache.iceberg.variants.Variant instances; any other runtime value encountered for a VARIANT-typed field throws UnsupportedOperationException with the value's Java class.

Source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:386

        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

  1. Ensure all Iceberg runtime jars (core and spark) are the same version
  2. Verify the value's class in the message and check which writer produced the data
  3. Upgrade Iceberg to a version where variant support matches your Spark version
  4. If reproducible, report as a bug with the value class from the message

Example fix

// before
mvn dependency:tree | grep iceberg  # mixed versions
// after
# pin all org.apache.iceberg modules to one version, e.g.
implementation("org.apache.iceberg:iceberg-spark-runtime-4.1_2.13:1.10.0")
Defensive patterns

Strategy: try-catch

Type guard

static boolean isIcebergVariant(Object v) { return v instanceof org.apache.iceberg.variants.Variant; }

Try / catch

try {
  VariantVal vv = row.getVariant(ordinal);
} catch (UnsupportedOperationException e) {
  throw new IllegalStateException("Non-Variant value in VARIANT column; check Iceberg version alignment: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Reading a VARIANT column where the in-memory value is neither an Iceberg Variant nor byte[] (the handled inputs) — typically indicates an internal bug or an unexpected writer format.

Common situations: Mixed Iceberg versions (table written by a different Iceberg runtime producing a different in-memory Variant representation), or custom extensions passing non-standard values through the scan pipeline.

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


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