apache/iceberg · error · UnsupportedOperationException
Unsupported term: ${term}
Error message
Unsupported term: ${term} What it means
ExpressionUtil's term-to-string helper (used by describe/sanitize/describe quoting) only knows NamedReference and BoundReference term types. Any other Term implementation passed to it hits this fallback UnsupportedOperationException. It signals an unhandled term variant in code that renders terms as strings.
Source
Thrown at api/src/main/java/org/apache/iceberg/expressions/ExpressionUtil.java:247
}
public static String describe(Term term) {
if (term instanceof UnboundTransform) {
return ((UnboundTransform<?, ?>) term).transform()
+ "("
+ describe(((UnboundTransform<?, ?>) term).ref())
+ ")";
} else if (term instanceof BoundTransform) {
return ((BoundTransform<?, ?>) term).transform()
+ "("
+ describe(((BoundTransform<?, ?>) term).ref())
+ ")";
} else if (term instanceof NamedReference) {
return ((NamedReference<?>) term).name();
} else if (term instanceof BoundReference) {
return ((BoundReference<?>) term).name();
} else {
throw new UnsupportedOperationException("Unsupported term: " + term);
}
}
public static <T> UnboundTerm<T> unbind(BoundTerm<T> term) {
if (term instanceof BoundTransform) {
BoundTransform<?, T> bound = (BoundTransform<?, T>) term;
return Expressions.transform(bound.ref().name(), bound.transform());
} else if (term instanceof BoundReference) {
return Expressions.ref(((BoundReference<T>) term).name());
}
throw new UnsupportedOperationException("Cannot unbind unsupported term: " + term);
}
@SuppressWarnings("unchecked")
public static <T> UnboundTerm<T> unbind(Term term) {
if (term instanceof UnboundTerm) {
return (UnboundTerm<T>) term;View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check the actual runtime type of the term before calling describe (NamedReference/BoundReference only)
- Upgrade Iceberg if using a new term type like UnboundTransform that a newer version handles
- Use ExpressionUtil.describe(Expression) on the full expression instead of describing terms directly
- If a custom Term was implemented, convert it to a supported reference or handle it before calling describe
Example fix
// before String desc = ExpressionUtil.describe(myUnboundTransformTerm); // after Term ref = term instanceof UnboundTransform ? ((UnboundTransform<?, ?>) term).ref() : term; String desc = ExpressionUtil.describe(ref);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(term instanceof NamedReference) && !(term instanceof BoundReference)) {
throw new IllegalArgumentException("describe() supports only named/bound references, got: " + term.getClass());
} Type guard
boolean isDescribableTerm(Term t) {
return t instanceof NamedReference || t instanceof BoundReference;
} Try / catch
try { return ExpressionUtil.describe(term); }
catch (UnsupportedOperationException e) { return term != null ? term.toString() : "<unknown term>"; } Prevention
- Only pass NamedReference or BoundReference to ExpressionUtil.describe
- Check Iceberg release notes for new term types before upgrading
- Handle UnboundTransform terms by extracting .ref() first
When it happens
Trigger: Calling ExpressionUtil.describe (or the sanitizing visitors that call it) with a Term that is neither NamedReference nor BoundReference, e.g. an UnboundTransform or a custom Term implementation.
Common situations: Custom expression extensions or new term types added in newer Iceberg versions but not yet handled by the describe helper; passing an UnboundTransform term from a transform expression into ExpressionUtil.describe; reflection-built terms from other modules.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Invalid aggregate:
- Found already bound predicate:
- Found already bound aggregate:
- does not implement eval(StructLike)
- does not implement eval(DataFile)
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/a0419e6a6e610a60.
Report an issue: GitHub.