apache/iceberg · error · IllegalArgumentException
Cannot convert JSON to literal: " + node
Error message
Cannot convert JSON to literal: " + node
What it means
ExpressionParser.asObject converts a JsonNode into a plain Java value (String, Double, Boolean, etc.) for use as a predicate literal. Node shapes it cannot map — objects, arrays, nulls, or other unsupported scalars — trigger this IllegalArgumentException. The JSON literal is not representable as an Iceberg predicate literal value.
Source
Thrown at core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java:399
type.equalsIgnoreCase(LITERAL), "Cannot parse type as a literal: %s", type);
return toValue.apply(JsonUtil.get(VALUE, valueNode));
}
// the node is a directly embedded literal value
return toValue.apply(valueNode);
}
private static Object asObject(JsonNode node) {
if (node.isIntegralNumber() && node.canConvertToLong()) {
return node.asLong();
} else if (node.isTextual()) {
return node.asText();
} else if (node.isFloatingPointNumber()) {
return node.asDouble();
} else if (node.isBoolean()) {
return node.asBoolean();
} else {
throw new IllegalArgumentException("Cannot convert JSON to literal: " + node);
}
}
@SuppressWarnings("unchecked")
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:View on GitHub (pinned to 86d9c8fc54)
Solutions
- Ensure predicate literal values in the JSON are plain scalars (string, number, boolean).
- Check for object/array-shaped literals and flatten or remove them before parsing.
- Upgrade Iceberg if the JSON was produced by a newer writer with extended literal encoding.
Example fix
// before
// JSON: {"type":"predicate","term":"col","op":"eq","values":[{"nested":1}]}
Expression e = ExpressionParser.fromJson(node);
// after
// JSON: {"type":"predicate","term":"col","op":"eq","values":[1]}
Expression e = ExpressionParser.fromJson(node); Defensive patterns
Strategy: validation
Validate before calling
JsonNode v = valueNode;
if (!(v.isTextual() || v.isNumber() || v.isBoolean())) {
throw new IllegalArgumentException("literal must be scalar: " + v.getNodeType());
} Type guard
boolean isScalarLiteral(JsonNode n) { return n.isTextual() || n.isNumber() || n.isBoolean(); } Try / catch
try {
Expression e = ExpressionParser.fromJson(node);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("malformed predicate literal in expression JSON", e);
} Prevention
- Emit only scalar literals (string/number/boolean) in predicate values arrays.
- Never embed nested objects/arrays as literal values.
- Round-trip test: toJson output must parse with fromJson.
When it happens
Trigger: ExpressionParser.fromJson on predicate JSON whose values array contains a literal node of an unsupported shape (nested object/array, null) instead of a scalar.
Common situations: Hand-written or tool-generated expression JSON with nested literal values; newer producers emitting literal encodings this parser version does not understand.
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 parse type as a reference: " + type
- Cannot parse reference (requires string or object): " + node
- AboveMax has no comparator
- BelowMin has no value
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/bd6be06b9dba7ebb.
Report an issue: GitHub.