apache/iceberg · error · ValidationException
Invalid term: , expected either a bound reference or…
Error message
Invalid term: %s, expected either a bound reference or transform
What it means
toTransform converts a bound term into its Transform: identity for a plain BoundReference, or the wrapped transform for a BoundTransform. Any other bound term shape cannot be expressed as a transform, so a ValidationException naming the term is thrown. This happens when partition terms passed to the spec update are not simple references or transformed references.
Solutions
- Build terms with Expressions.ref(column) or Expressions.transform(ref, transform) so they bind to BoundReference/BoundTransform
- Check the bound term type before passing it into the spec update
- Verify the term was bound against the table schema correctly
Example fix
// before
Term term = myCustomTermBuilder.build(); // not a BoundReference/BoundTransform
specUpdate.transform(term); // throws
// after
Term term = Expressions.transform(Expressions.ref("ts"), Expressions.day());
specUpdate.transform(term); Defensive patterns
Strategy: validation
Validate before calling
if (!(term instanceof BoundReference) && !(term instanceof BoundTransform)) { throw new IllegalArgumentException("term must be a reference or transform"); } Try / catch
catch (ValidationException e) { /* rebuild the term with Expressions helpers */ } Prevention
- Always construct terms via the Expressions helper API
- Bind terms against the table schema before passing to spec updates
- Avoid custom Term implementations
When it happens
Trigger: Calling transform(Term)/addField paths in BaseUpdatePartitionSpec with a term that resolves to neither BoundReference nor BoundTransform — typically a custom, aggregate, or wrongly-constructed bound term.
Common situations: Programmatic term construction producing unexpected bound term implementations; passing projected or aggregate terms where a simple column reference or transform is required.
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
- Can't index multiple DVs for
- Cannot add duplicate partition field name
- Cannot add fields to map keys:
- Cannot add partition field to non-Iceberg table: $table
- Cannot alter map keys:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/89f7b40c99feb25e.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/BaseUpdatePartitionSpec.java:370
int sourceId = boundTerm.ref().fieldId();
Transform<?, ?> transform = toTransform(boundTerm);
Type fieldType = schema.findType(sourceId);
if (fieldType != null) {
transform = Transforms.fromString(fieldType, transform.toString());
} else {
transform = Transforms.fromString(transform.toString());
}
return Pair.of(sourceId, transform);
}
private Transform<?, ?> toTransform(BoundTerm<?> term) {
if (term instanceof BoundReference) {
return Transforms.identity();
} else if (term instanceof BoundTransform) {
return ((BoundTransform<?, ?>) term).transform();
} else {
throw new ValidationException(
"Invalid term: %s, expected either a bound reference or transform", term);
}
}
private void checkForRedundantAddedPartitions(PartitionField field) {
if (isTimeTransform(field)) {
PartitionField timeField = addedTimeFields.get(field.sourceId());
Preconditions.checkArgument(
timeField == null,
"Cannot add redundant partition field: %s conflicts with %s",
timeField,
field);
addedTimeFields.put(field.sourceId(), field);
}
}
private static Map<String, PartitionField> indexSpecByName(PartitionSpec spec) {
ImmutableMap.Builder<String, PartitionField> builder = ImmutableMap.builder();View on GitHub (pinned to 86d9c8fc54)