json-path/JsonPath · error · InvalidPathException

Expected json node

Error message

Expected json node

What it means

ValueNode's base asJsonNode() throws InvalidPathException("Expected json node") when code (evaluate, vn, valueNode paths) calls asJsonNode() on a node that is not a JsonNode (a node wrapping a parsed document). This happens when a filter expects an embedded document/array operand but gets a scalar ValueNode such as a string or number. It is part of JsonPath's default-throw type-cast family on ValueNode.

Source

Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java:64

    public StringNode asStringNode() {
        throw new InvalidPathException("Expected string node");
    }

    public boolean isBooleanNode() {
        return false;
    }

    public BooleanNode asBooleanNode() {
        throw new InvalidPathException("Expected boolean node");
    }

    public boolean isJsonNode() {
        return false;
    }

    public JsonNode asJsonNode() {
        throw new InvalidPathException("Expected json node");
    }

    public boolean isPredicateNode() {
        return false;
    }

    public PredicateNode asPredicateNode() {
        throw new InvalidPathException("Expected predicate node");
    }

    public boolean isValueListNode() {
        return false;
    }

    public ValueListNode asValueListNode() {
        throw new InvalidPathException("Expected value list node");
    }

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Ensure the operand field is a real JSON object/array in the document (parse embedded JSON strings before evaluation)
  2. Rewrite the filter to operate on the nested field's properties rather than on the whole document value
  3. Validate the document shape (e.g. that the field is an object) before running the filter
  4. Catch InvalidPathException and fall back to scalar-comparison logic

Example fix

// before
String meta = "{}"; // embedded JSON stored as string; filter @.meta in @.defaults fails
// after
Object meta = JsonPath.parse(metaJsonString).json(); // real object node; filter works
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = JsonPath.parse(json).read("$.item.meta");
if (!(v instanceof Map) && !(v instanceof List)) throw new IllegalArgumentException("meta must be a JSON object or array");

Type guard

static boolean isDocumentOperand(Object o) { return o instanceof Map || o instanceof List; }

Try / catch

try {
    return JsonPath.parse(json).read("$.items[?(@.meta in @.defaults)]");
} catch (InvalidPathException e) {
    // operand is scalar, not a document; fallback to scalar logic
    return fallbackScalarFilter(json);
}

Prevention

When it happens

Trigger: A filter or API expecting a nested document operand — e.g. an operator that calls asJsonNode() on the evaluated value of a path — receiving a scalar, e.g. $.items[?(@.meta in @.defaults)] where @.meta resolves to a string instead of an object/array. Also direct calls to valueNode()/vn conversion paths on non-document values.

Common situations: Comparing or nesting whole sub-documents in filters when some records store the field as a JSON string rather than a parsed object; schema drift where an array field sometimes holds a plain value.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11). Data as JSON: /api/errors/b16800ba2805ca4c. Report an issue: GitHub.