apache/iceberg · error · java.lang.IllegalArgumentException
Invalid projection for field <field.name()>: <e.getMessage()
Error message
Invalid projection for field <field.name()>: <e.getMessage()>
What it means
PruneColumnsWithoutReordering.field projects a requested field type onto the current struct type during column pruning. If computing the projection throws IllegalArgumentException, it is re-wrapped with the field name: 'Invalid projection for field <name>: <msg>', giving context about which field failed.
Source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/PruneColumnsWithoutReordering.java:138
if (filterRefs.contains(field.fieldId())) {
return field.type();
}
return null;
}
int fieldIndex = requestedStruct.fieldIndex(field.name());
StructField requestedField = requestedStruct.fields()[fieldIndex];
Preconditions.checkArgument(
requestedField.nullable() || field.isRequired(),
"Cannot project an optional field as non-null: %s",
field.name());
this.current = requestedField.dataType();
try {
return fieldResult.get();
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(
"Invalid projection for field " + field.name() + ": " + e.getMessage(), e);
} finally {
this.current = requestedStruct;
}
}
@Override
public Type list(Types.ListType list, Supplier<Type> elementResult) {
Preconditions.checkArgument(current instanceof ArrayType, "Not an array: %s", current);
ArrayType requestedArray = (ArrayType) current;
Preconditions.checkArgument(
requestedArray.containsNull() || !list.isElementOptional(),
"Cannot project an array of optional elements as required elements: %s",
requestedArray);
this.current = requestedArray.elementType();
try {View on GitHub (pinned to 86d9c8fc54)
Solutions
- Read the inner message for the actual type mismatch and align the requested schema with the table's current schema
- Refresh cached tables/dataframes so plans use the latest table schema
- Re-check schema evolution changes that altered this field's type
- Report upstream if the mismatch comes from Iceberg's own pruning with identical schemas
Example fix
// before
spark.table("t").select("evolved_struct.newly_renamed_field")
// after
spark.table("t") // refresh plan against current schema
.select("evolved_struct.newly_renamed_field") Defensive patterns
Strategy: try-catch
Try / catch
try {
df = spark.read().format("iceberg").load(path);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Invalid projection for field")) {
log.error("Schema drift on field; refresh schema. {}", e.getMessage(), e);
spark.catalog().refreshTable(path);
} else throw e;
} Prevention
- spark.catalog().refreshTable after schema evolution
- Avoid long-lived cached DataFrames across schema changes
- Test projections after type-evolution operations
When it happens
Trigger: Schema pruning encounters a requested type incompatible with the table's current type for a given field (e.g. mismatched struct/array/map shapes after schema evolution or incompatible requested schema).
Common situations: Evolving a column's type in the table after queries/plans were built against the old schema; requesting a projection schema that diverges from the table schema; partition-transform mismatches.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid projection for field ${field.name()}: ${e.getMessage
- Cannot find field %s in %s
- Unknown field ordinal: ${basePos}
- Invalid projection for field ${field.name()}: ${e.getMessage
- Spark does not support time fields
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/81b870601cf5865b.
Report an issue: GitHub.