{"record":{"id":"05d60d51116b6b68","repo":"apache/iceberg","slug":"variant-column-has-only-2-children-got-ordinal","errorCode":null,"errorMessage":"Variant column has only 2 children, got ordinal: ${ordinal}","messagePattern":"Variant column has only 2 children, got ordinal: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/data/vectorized/VariantColumnVector.java","lineNumber":74,"sourceCode":"  public int numNulls() {\n    return valueChild.numNulls();\n  }\n\n  @Override\n  public boolean isNullAt(int rowId) {\n    return valueChild.isNullAt(rowId);\n  }\n\n  // getChild is what getVariant() calls: child(0) = value, child(1) = metadata\n  @Override\n  public ColumnVector getChild(int ordinal) {\n    if (ordinal == 0) {\n      return valueChild;\n    } else if (ordinal == 1) {\n      return metadataChild;\n    }\n\n    throw new IllegalArgumentException(\n        \"Variant column has only 2 children, got ordinal: \" + ordinal);\n  }\n\n  @Override\n  public boolean getBoolean(int rowId) {\n    throw unsupported();\n  }\n\n  @Override\n  public byte getByte(int rowId) {\n    throw unsupported();\n  }\n\n  @Override\n  public short getShort(int rowId) {\n    throw unsupported();\n  }\n","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/data/vectorized/VariantColumnVector.java#L56-L92","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Align Spark and Iceberg versions so variant support matches (Iceberg Spark 4.0 with matching Spark build)","Do not access variant child vectors directly — query the variant column as a whole","Check for duplicate/mixed iceberg-spark jars and clean the classpath","If triggered by a stock query, file an Iceberg issue with the query plan"],"exampleFix":"// before\nvector.getChild(2) // variant has only value(0) and metadata(1)\n// after\nvector.getChild(0) // value child\nvector.getChild(1) // metadata child","handlingStrategy":"validation","validationCode":"int ordinal = /* desired */; if (!\"variant\".equals(vector.dataType().simpleString()) || ordinal > 1) { throw new IllegalArgumentException(\"variant children are 0=value, 1=metadata\"); }","typeGuard":"Integer variantChild(int ordinal) { return (ordinal == 0 || ordinal == 1) ? ordinal : null; }","tryCatchPattern":"try { child = variantVector.getChild(ordinal); } catch (IllegalArgumentException e) { // use ordinal 0 or 1 only }\nchild = variantVector.getChild(Math.min(ordinal, 1));","preventionTips":["Treat variant as opaque; access only value(0)/metadata(1)","Align Spark and Iceberg builds that both support the variant type","Don't hand-construct variant child ordinals from engine internals"],"tags":["spark","variant","vectorized-read"],"backgroundTag":"index-out-of-bounds","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}