apache/iceberg · error · UnsupportedOperationException
Cannot write unsupported term
Error message
Cannot write unsupported term: ${term} What it means
When serializing a predicate's term to JSON, ExpressionParser only knows how to write Transform-terminated terms and plain References; any other Term implementation hits this UnsupportedOperationException. It signals a term type the parser's JSON format cannot represent.
Solutions
- Use only standard Iceberg terms (References, Transforms) in expressions you serialize.
- Check the term's class in the cause of the failure and convert it to a Reference or standard transform before serializing.
- If you need custom terms, serialize them with your own parser rather than ExpressionParser.
Example fix
// before
ExpressionParser.toJson(Expressions.predicate("op", customTerm, value)); // customTerm: unsupported Term
// after
UnboundTerm<?> ref = Expressions.ref("column_name");
ExpressionParser.toJson(Expressions.predicate("op", ref, value)); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(expr instanceof Predicate)) throw new IllegalArgumentException("only predicates are serializable");
Term t = ((Predicate) expr).term();
if (!(t instanceof Reference) && !(hasSupportedTransform(t))) throw new IllegalArgumentException("unsupported term: " + t.getClass()); Type guard
boolean serializableTerm(Term t) { return t instanceof Reference || t instanceof UnboundTransform; } Try / catch
try {
ExpressionParser.toJson(expr, gen);
} catch (UnsupportedOperationException e) {
throw new IllegalArgumentException("expression contains a non-serializable term", e);
} Prevention
- Build expressions only with Expressions factory methods (standard references and transforms).
- Avoid custom Term implementations when serializing with ExpressionParser.
- Test round-trip toJson/fromJson for any custom expression construction.
When it happens
Trigger: Calling ExpressionParser.toJson on an expression whose predicate term is a custom or unexpected Term implementation (neither NamedReference-derived nor a transform).
Common situations: Custom expression extensions or third-party Term implementations; bugs where an internal term type (e.g. an unbound transform with no reference) is fed to the parser.
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
- Cannot evaluate
- Cannot serialize an eager input file
- Cannot serialize FileIO
- Cannot serialize type: + typeId
- does not implement countFor(DataFile)
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/6cf3046157dc499d.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java:250
private String operationType(Expression.Operation op) {
return op.toString().replace('_', '-').toLowerCase(Locale.ROOT);
}
private void term(Term term) throws IOException {
if (term instanceof UnboundTransform) {
UnboundTransform<?, ?> transform = (UnboundTransform<?, ?>) term;
transform(transform.transform().toString(), transform.ref().name());
return;
} else if (term instanceof BoundTransform) {
BoundTransform<?, ?> transform = (BoundTransform<?, ?>) term;
transform(transform.transform().toString(), transform.ref().name());
return;
} else if (term instanceof Reference) {
gen.writeString(((Reference<?>) term).name());
return;
}
throw new UnsupportedOperationException("Cannot write unsupported term: " + term);
}
private void transform(String transform, String name) throws IOException {
gen.writeStartObject();
gen.writeStringField(TYPE, TRANSFORM);
gen.writeStringField(TRANSFORM, transform);
gen.writeStringField(TERM, name);
gen.writeEndObject();
}
}
public static Expression fromJson(String json) {
return fromJson(json, null);
}
public static Expression fromJson(JsonNode json) {
return fromJson(json, null);
}View on GitHub (pinned to 86d9c8fc54)