apache/iceberg · error · IllegalArgumentException

Expected one (and same) ORC type for list elements, got:

Error message

Expected one (and same) ORC type for list elements, got: 

What it means

ListWriter in SparkOrcValueWriters builds the ORC writer for a Spark array column. It requires the ORC schema's children list for the list column to contain exactly one element type (the ORC 'list' group has a single 'element' child); anything else means the ORC type tree passed in is malformed or misaligned with the Spark schema. The writer throws IllegalArgumentException during writer construction, before any rows are written.

Solutions

  1. Inspect the ORC schema of the target column (TypeDescription.getChildren()) and ensure the list group has exactly one child element type
  2. Regenerate writers from the Iceberg table schema (spark.table(...).schema()) rather than from a manually constructed ORC type
  3. Check whether a custom ORC schema override/evolution is misaligned with the Spark schema and fix or remove it
  4. If it occurs after a schema evolution, rewrite the affected data files or fix the schema mapping logic

Example fix

// before
TypeDescription listType = TypeDescription.createList(nullTypeWithNoChild);
// after
TypeDescription elementType = TypeDescription.createLong();
TypeDescription listType = TypeDescription.createList(elementType); // exactly one child
Defensive patterns

Strategy: validation

Validate before calling

List<TypeDescription> children = listType.getChildren();
if (children.size() != 1) {
  throw new IllegalStateException("ORC list type must have exactly one element child, got: " + listType);
}

Type guard

boolean isValidOrcList(TypeDescription t) {
  return t.getCategory() == TypeDescription.Category.LIST && t.getChildren().size() == 1;
}

Try / catch

try {
  spark.write().format("iceberg").save(orcTarget);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Expected one (and same) ORC type for list elements")) {
    // validate/repair the ORC schema, then retry
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling SparkOrcWriter.createValueWriter (via a write path from Spark) for an array column whose TypeDescription children list has 0 or more than 1 element, e.g. a hand-built ORC TypeDescription whose list group lacks exactly one 'element' child.

Common situations: Writing Iceberg ORC files through Spark with a corrupted or externally constructed ORC schema; schema/format mismatches between Iceberg's table schema and the file's ORC type tree; bugs in schema evolution code that reassembles TypeDescription trees.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/data/SparkOrcValueWriters.java:137

  }

  private static class Decimal38Writer implements OrcValueWriter<Decimal> {

    @Override
    public void nonNullWrite(int rowId, Decimal decimal, ColumnVector output) {
      ((DecimalColumnVector) output)
          .vector[rowId].set(HiveDecimal.create(decimal.toJavaBigDecimal()));
    }
  }

  private static class ListWriter<T> implements OrcValueWriter<ArrayData> {
    private final OrcValueWriter<T> writer;
    private final SparkOrcWriter.FieldGetter<T> fieldGetter;

    @SuppressWarnings("unchecked")
    ListWriter(OrcValueWriter<T> writer, List<TypeDescription> orcTypes) {
      if (orcTypes.size() != 1) {
        throw new IllegalArgumentException(
            "Expected one (and same) ORC type for list elements, got: " + orcTypes);
      }
      this.writer = writer;
      this.fieldGetter =
          (SparkOrcWriter.FieldGetter<T>) SparkOrcWriter.createFieldGetter(orcTypes.get(0));
    }

    @Override
    public void nonNullWrite(int rowId, ArrayData value, ColumnVector output) {
      ListColumnVector cv = (ListColumnVector) output;
      // record the length and start of the list elements
      cv.lengths[rowId] = value.numElements();
      cv.offsets[rowId] = cv.childCount;
      cv.childCount = (int) (cv.childCount + cv.lengths[rowId]);
      // make sure the child is big enough
      growColumnVector(cv.child, cv.childCount);
      // Add each element
      for (int e = 0; e < cv.lengths[rowId]; ++e) {

View on GitHub (pinned to 86d9c8fc54)