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
- Inspect the ORC schema of the target column (TypeDescription.getChildren()) and ensure the list group has exactly one child element type
- Regenerate writers from the Iceberg table schema (spark.table(...).schema()) rather than from a manually constructed ORC type
- Check whether a custom ORC schema override/evolution is misaligned with the Spark schema and fix or remove it
- 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
- Always derive ORC TypeDescriptions from the Iceberg table schema, never hand-build them
- After schema evolution, validate that ORC children lists match the Iceberg types before writing
- Add a pre-write unit test asserting writer construction succeeds for every column of the schema
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
- Expected two ORC type descriptions for a map, got:
- Encountered an unsupported ORC type during a write from…
- Cannot add column since setting default values in Spark is…
- Cannot add column since setting default values in Spark is…
- Cannot convert unsupported type to Spark
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)