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

  1. Make the term a column-name string or a valid term object in the JSON.
  2. Validate the JSON structure before parsing (term must be textual or object).
  3. 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

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/b2bed8b38ac61974. Report an issue: GitHub.