apache/iceberg · error · IllegalArgumentException

Variant column has only 2 children, got ordinal

Error message

Variant column has only 2 children, got ordinal: ${ordinal}

What it means

VariantColumnVector exposes a Spark variant column as exactly two children: value (ordinal 0) and metadata (ordinal 1). Requesting any other child ordinal is invalid and throws IllegalArgumentException.

Solutions

  1. Align Spark and Iceberg versions so variant support matches (Iceberg Spark 4.0 with matching Spark build)
  2. Do not access variant child vectors directly — query the variant column as a whole
  3. Check for duplicate/mixed iceberg-spark jars and clean the classpath
  4. If triggered by a stock query, file an Iceberg issue with the query plan

Example fix

// before
vector.getChild(2) // variant has only value(0) and metadata(1)
// after
vector.getChild(0) // value child
vector.getChild(1) // metadata child
Defensive patterns

Strategy: validation

Validate before calling

int ordinal = /* desired */; if (!"variant".equals(vector.dataType().simpleString()) || ordinal > 1) { throw new IllegalArgumentException("variant children are 0=value, 1=metadata"); }

Type guard

Integer variantChild(int ordinal) { return (ordinal == 0 || ordinal == 1) ? ordinal : null; }

Try / catch

try { child = variantVector.getChild(ordinal); } catch (IllegalArgumentException e) { // use ordinal 0 or 1 only }
child = variantVector.getChild(Math.min(ordinal, 1));

Prevention

When it happens

Trigger: Calling getChild(ordinal) with ordinal >= 2 on a variant column vector — typically a reader bug or a Spark plan that walks variant children beyond the two defined ones.

Common situations: Version mismatches between Spark's variant representation and Iceberg's VariantColumnVector; malformed or hand-built expressions accessing variant internals; schema evolution where a non-variant vector is assumed.

Related errors


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

Appendix: source

Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/data/vectorized/VariantColumnVector.java:74

  public int numNulls() {
    return valueChild.numNulls();
  }

  @Override
  public boolean isNullAt(int rowId) {
    return valueChild.isNullAt(rowId);
  }

  // getChild is what getVariant() calls: child(0) = value, child(1) = metadata
  @Override
  public ColumnVector getChild(int ordinal) {
    if (ordinal == 0) {
      return valueChild;
    } else if (ordinal == 1) {
      return metadataChild;
    }

    throw new IllegalArgumentException(
        "Variant column has only 2 children, got ordinal: " + ordinal);
  }

  @Override
  public boolean getBoolean(int rowId) {
    throw unsupported();
  }

  @Override
  public byte getByte(int rowId) {
    throw unsupported();
  }

  @Override
  public short getShort(int rowId) {
    throw unsupported();
  }

View on GitHub (pinned to 86d9c8fc54)