apache/iceberg · error · IllegalArgumentException
Cannot parse reference (requires string or object): " + node
Error message
Cannot parse reference (requires string or object): " + node
What it means
ExpressionParser.term(JsonNode) expects a term node to be either a plain string (a column reference name) or an object with a recognized "type". Any other JSON shape (number, array, null, boolean) reaches this final IllegalArgumentException. The term portion of the predicate JSON is structurally malformed.
Source
Thrown at core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java:422
private static <T> UnboundTerm<T> term(JsonNode node) {
if (node.isTextual()) {
return Expressions.ref(node.asText());
} else if (node.isObject()) {
String type = JsonUtil.getString(TYPE, node);
switch (type) {
case REFERENCE:
return Expressions.ref(JsonUtil.getString(TERM, node));
case TRANSFORM:
UnboundTerm<T> child = term(JsonUtil.get(TERM, node));
String transform = JsonUtil.getString(TRANSFORM, node);
return (UnboundTerm<T>)
Expressions.transform(child.ref().name(), Transforms.fromString(transform));
default:
throw new IllegalArgumentException("Cannot parse type as a reference: " + type);
}
}
throw new IllegalArgumentException(
"Cannot parse reference (requires string or object): " + node);
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Make the term a column-name string or a valid term object in the JSON.
- Validate the JSON structure before parsing (term must be textual or object).
- Regenerate the expression JSON from the source expression with ExpressionParser.toJson.
Example fix
// before
// {"type":"predicate","op":"eq","term":["col"],"values":[1]}
Expression e = ExpressionParser.fromJson(node);
// after
// {"type":"predicate","op":"eq","term":"col","values":[1]}
Expression e = ExpressionParser.fromJson(node); Defensive patterns
Strategy: type-guard
Validate before calling
JsonNode t = predNode.get("term");
if (t == null || !(t.isTextual() || t.isObject())) {
throw new IllegalArgumentException("term must be a string or object");
} Type guard
boolean isWellFormedTerm(JsonNode n) { return n != null && (n.isTextual() || n.isObject()); } Try / catch
try {
Expression e = ExpressionParser.fromJson(node);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("predicate term node is malformed", e);
} Prevention
- Always emit "term" as a column-name string or a typed object.
- Validate predicate JSON structure before calling fromJson.
- Use toJson output as the canonical template for predicate JSON.
When it happens
Trigger: ExpressionParser.fromJson on predicate JSON where "term" is not a string or object — e.g. a number, array, or missing/null node.
Common situations: Hand-written expression JSON; tooling that emits the wrong structure for terms; truncation/corruption of stored metadata.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Unsupported operation: " + op
- Cannot convert JSON to literal: " + node
- Cannot parse type as a reference: " + type
- Unknown task type:
- Cannot parse type from json:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/b2bed8b38ac61974.
Report an issue: GitHub.