Describe the bug
Function composition through value() behaves differently from the equivalent singular-query argument. Arrays and objects cause a ValueType error, while an empty array silently stops matching. A string control succeeds in both forms.
Actual
Save the following as repro.mjs.
import { JSONPathJS } from 'jsonpath-js';
for (const value of [[], [1], {x: 1}, 'x']) {
const document = [{a: value}];
for (const query of ['$[?length(@.a) > -1]', '$[?length(value(@.a)) > -1]']) {
try {
console.log(JSON.stringify({document, query, result: new JSONPathJS(query).find(document)}));
} catch (error) {
console.log(JSON.stringify({document, query, error: error.message}));
}
}
}
Run:
npm install jsonpath-js@0.3.1
node repro.mjs
Observed output:
{"document":[{"a":[]}],"query":"$[?length(@.a) > -1]","result":[{"a":[]}]}
{"document":[{"a":[]}],"query":"$[?length(value(@.a)) > -1]","result":[]}
{"document":[{"a":[1]}],"query":"$[?length(@.a) > -1]","result":[{"a":[1]}]}
{"document":[{"a":[1]}],"query":"$[?length(value(@.a)) > -1]","error":"Invalid argument type \"[1]\" is not a ValueType"}
{"document":[{"a":{"x":1}}],"query":"$[?length(@.a) > -1]","result":[{"a":{"x":1}}]}
{"document":[{"a":{"x":1}}],"query":"$[?length(value(@.a)) > -1]","error":"Invalid argument type \"{\"x\":1}\" is not a ValueType"}
{"document":[{"a":"x"}],"query":"$[?length(@.a) > -1]","result":[{"a":"x"}]}
{"document":[{"a":"x"}],"query":"$[?length(value(@.a)) > -1]","result":[{"a":"x"}]}
Expected
Each pair of queries should return the same input object. All four inputs have a defined nonnegative length, and value(@.a) receives exactly one node even when that node's value is an empty array.
RFC 9535 §2.4.8 returns the value of the single node; §2.4.4 permits length of a string, array, or object. §2.4.3 permits a ValueType-producing function as a ValueType argument:
https://www.rfc-editor.org/rfc/rfc9535.html#section-2.4.8
https://www.rfc-editor.org/rfc/rfc9535.html#section-2.4.4
https://www.rfc-editor.org/rfc/rfc9535.html#section-2.4.3
Environment
- Package: jsonpath-js 0.3.1
- Runtime: Node.js 23.11.0
- OS: macOS 26.6.2, Apple Silicon / arm64
- Reproduced: 2026-09-11
Additional context
This uses new JSONPathJS(query).find(document). The empty array is the value of one selected node; it is not an empty node list. The public API either throws on valid composition or silently loses a matching record, depending on the composite value.
jsonpath-js-reproduction.zip
Describe the bug
Function composition through
value()behaves differently from the equivalent singular-query argument. Arrays and objects cause a ValueType error, while an empty array silently stops matching. A string control succeeds in both forms.Actual
Save the following as
repro.mjs.Run:
Observed output:
{"document":[{"a":[]}],"query":"$[?length(@.a) > -1]","result":[{"a":[]}]} {"document":[{"a":[]}],"query":"$[?length(value(@.a)) > -1]","result":[]} {"document":[{"a":[1]}],"query":"$[?length(@.a) > -1]","result":[{"a":[1]}]} {"document":[{"a":[1]}],"query":"$[?length(value(@.a)) > -1]","error":"Invalid argument type \"[1]\" is not a ValueType"} {"document":[{"a":{"x":1}}],"query":"$[?length(@.a) > -1]","result":[{"a":{"x":1}}]} {"document":[{"a":{"x":1}}],"query":"$[?length(value(@.a)) > -1]","error":"Invalid argument type \"{\"x\":1}\" is not a ValueType"} {"document":[{"a":"x"}],"query":"$[?length(@.a) > -1]","result":[{"a":"x"}]} {"document":[{"a":"x"}],"query":"$[?length(value(@.a)) > -1]","result":[{"a":"x"}]}Expected
Each pair of queries should return the same input object. All four inputs have a defined nonnegative length, and
value(@.a)receives exactly one node even when that node's value is an empty array.RFC 9535 §2.4.8 returns the value of the single node; §2.4.4 permits length of a string, array, or object. §2.4.3 permits a ValueType-producing function as a ValueType argument:
https://www.rfc-editor.org/rfc/rfc9535.html#section-2.4.8
https://www.rfc-editor.org/rfc/rfc9535.html#section-2.4.4
https://www.rfc-editor.org/rfc/rfc9535.html#section-2.4.3
Environment
Additional context
This uses
new JSONPathJS(query).find(document). The empty array is the value of one selected node; it is not an empty node list. The public API either throws on valid composition or silently loses a matching record, depending on the composite value.jsonpath-js-reproduction.zip