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
A Spark Variant column vector is composed of exactly two children: value (ordinal 0) and metadata (ordinal 1). getChild is called by the engine to descend into struct-like children; any ordinal outside 0..1 indicates the engine is treating the variant vector as a struct with more fields than it has, so the vector throws IllegalArgumentException.
Solutions
- Verify the Spark version matches the icebberg-spark-4.1 module expectations (variant support requires recent Spark 4.x)
- Don't index VariantColumnVector as a struct beyond its two children; use getVariant(rowId) style access instead
- Check the physical schema wasn't altered so the variant column resolves as a struct with extra fields
Example fix
// before
ColumnVector child = variantVector.getChild(2);
// after
if (ordinal < variantVector.getNumChildren()) {
ColumnVector child = variantVector.getChild(ordinal);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (ordinal < 0 || ordinal >= 2) {
throw new IllegalArgumentException("VariantColumnVector exposes only ordinals 0 (value) and 1 (metadata)");
} Type guard
boolean isValidVariantChildOrdinal(int ordinal) { return ordinal == 0 || ordinal == 1; } Try / catch
try {
ColumnVector child = variantVector.getChild(ordinal);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Variant column has only 2 children")) {
throw new IllegalStateException("Wrong ordinal for variant child; use 0=value, 1=metadata", e);
}
throw e;
} Prevention
- Treat VariantColumnVector as a 2-child vector only
- Match Spark and Iceberg versions so variant layouts agree
- Use the variant accessor APIs instead of struct-style child indexing
When it happens
Trigger: Calling getChild(ordinal) on VariantColumnVector with ordinal >= 2, typically from a Spark plan that misinterprets the variant column's internal layout or indexes a wrong field position.
Common situations: Version drift between Spark's VariantVal handling and Iceberg's variant vector implementation; custom readers/code touching the variant column vector internals with wrong ordinals.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Variant column has only 2 children, got ordinal
- does not implement getArray
- does not implement getMap
- Couldn't set Arrow properties, which may impact read…
- Couldn't set Arrow properties, which may impact read…
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/44f289c3691373dc.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.1/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)