{"record":{"id":"0239cfca08a7a4a7","repo":"json-path/JsonPath","slug":"expected-path-node","errorCode":null,"errorMessage":"Expected path node","messagePattern":"Expected path node","errorType":"exception","errorClass":"InvalidPathException","httpStatus":null,"severity":"error","filePath":"json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java","lineNumber":32,"sourceCode":"\npublic abstract class ValueNode {\n\n    public abstract Class<?> type(Predicate.PredicateContext ctx);\n\n    public boolean isPatternNode() {\n        return false;\n    }\n\n    public PatternNode asPatternNode() {\n        throw new InvalidPathException(\"Expected regexp node\");\n    }\n\n    public boolean isPathNode() {\n        return false;\n    }\n\n    public PathNode asPathNode() {\n        throw new InvalidPathException(\"Expected path node\");\n    }\n\n    public boolean isNumberNode() {\n        return false;\n    }\n\n    public NumberNode asNumberNode() {\n        throw new InvalidPathException(\"Expected number node\");\n    }\n\n    public boolean isStringNode() {\n        return false;\n    }\n\n    public StringNode asStringNode() {\n        throw new InvalidPathException(\"Expected string node\");\n    }\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/json-path/JsonPath/blob/62a4c9f0f65ba3f625aa0867d64c528ba72d09ec/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java#L14-L50","documentation":"ValueNode.asPathNode() is the default implementation that every non-path ValueNode inherits; only a real PathNode can be converted. When filter code (e.g. pathNode() or the right() operand handling) calls asPathNode() on a node that is actually a literal (string/number/boolean/json) node, the library throws InvalidPathException(\"Expected path node\").","triggerScenarios":"A filter predicate where one side must resolve to a JSON path (e.g. comparisons of path-to-path or @.a == @.b style nodes) but the operand parsed as a literal value; calling asPathNode() on a ValueNode obtained from parsing a quoted string or number.","commonSituations":"Dynamically built filter nodes where a raw string was used where a PathNode was required; expressions referencing document fields that got quoted accidentally, turning them into string nodes; custom filter evaluation code assuming both operands are path nodes.","solutions":["Call isPathNode() to check the node kind before invoking asPathNode(), and handle literal nodes explicitly.","Ensure the operand is an unquoted path expression (e.g. @.price) so the parser produces a PathNode, not a string literal.","When constructing filter nodes programmatically, wrap path expressions in ValueNode.PathNode rather than passing raw literals.","Add a debug log of the node's class (e.g. node.getClass()) at the call site to see which literal type leaked in."],"exampleFix":"// before\nValueNode node = new ValueNode.StringNode(\"@.price\");\nnode.asPathNode(); // throws\n\n// after\nValueNode node = new ValueNode.PathNode(Path.compile(\"@.price\"));\nif (node.isPathNode()) {\n    node.asPathNode();\n}","handlingStrategy":"type-guard","validationCode":"// Java: ensure path operands are unquoted path expressions starting with @ or $\nvoid validatePathOperand(String expr) {\n    if (!(expr.startsWith(\"@.\") || expr.startsWith(\"$\"))) {\n        throw new IllegalArgumentException(\"Expected a path operand like @.field, got: \" + expr);\n    }\n}","typeGuard":"boolean asPathSafe(ValueNode node) {\n    return node.isPathNode(); // only then call node.asPathNode()\n}","tryCatchPattern":"try {\n    return node.asPathNode();\n} catch (InvalidPathException e) {\n    if (e.getMessage().equals(\"Expected path node\")) {\n        throw new IllegalStateException(\"Expected a PathNode, got \" + node.getClass().getSimpleName(), e);\n    }\n    throw e;\n}","preventionTips":["Check isPathNode() before asPathNode().","Do not quote path operands in filters; quoting turns them into StringNodes.","Use ValueNode.PathNode (or Path.compile) when constructing nodes programmatically.","Log node.getClass().getSimpleName() at failing call sites to spot literal leakage."],"tags":["json-path","filter-evaluation","path-node","type-error"],"backgroundTag":"type-mismatch","analyzedSha":"62a4c9f0f65ba3f625aa0867d64c528ba72d09ec","analyzedAt":"2026-09-11T11:36:00.448Z","contentChangedAt":"2026-09-11T11:36:00.448Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}