json-path/JsonPath · error · JsonPathException
Could not convert
Error message
Could not convert
What it means
When evaluating a filter ValueNode created from a path (PathJsonPathValueNode-style), the library evaluates the sub-path against the document and converts the result into a ValueNode (String, Boolean, JsonNode, etc.). If the result's type is none of the supported shapes (Number/String/Boolean/OffsetDateTime/null/array/map), it throws JsonPathException('Could not convert ... to a ValueNode').
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java:705
Object res;
if (ctx instanceof PredicateContextImpl) {
//This will use cache for document ($) queries
PredicateContextImpl ctxi = (PredicateContextImpl) ctx;
res = ctxi.evaluate(path);
} else {
Object doc = path.isRootPath() ? ctx.root() : ctx.item();
res = path.evaluate(doc, ctx.root(), ctx.configuration()).getValue();
}
res = ctx.configuration().jsonProvider().unwrap(res);
if (res instanceof Number) return ValueNode.createNumberNode(res.toString());
else if (res instanceof String) return ValueNode.createStringNode(res.toString(), false);
else if (res instanceof Boolean) return ValueNode.createBooleanNode(res.toString());
else if (res instanceof OffsetDateTime) return ValueNode.createOffsetDateTimeNode(res.toString()); //workaround for issue: https://github.com/json-path/JsonPath/issues/613
else if (res == null) return NULL_NODE;
else if (ctx.configuration().jsonProvider().isArray(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, List.class, ctx.configuration()));
else if (ctx.configuration().jsonProvider().isMap(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, Map.class, ctx.configuration()));
else throw new JsonPathException("Could not convert " + res.getClass().toString()+":"+ res.toString() + " to a ValueNode");
} catch (PathNotFoundException e) {
return UNDEFINED;
}
}
}
}
}
View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Upgrade json-path to a version whose ValueNode supports numeric conversion, or ensure the compared value is a String/Boolean/List/Map.
- Configure Configuration with a MappingProvider that maps values to standard Java types (e.g. JacksonMappingProvider).
- Cast the comparison operand to a supported type in the predicate, e.g. compare strings instead of raw numbers.
- Catch JsonPathException and fall back to evaluating the predicate in application code.
Example fix
// before
JsonPath.parse(json).set("$[?(@.count == 5)].status", "ok"); // count maps to Integer -> not convertible (old versions)
// after
Configuration cfg = Configuration.builder().mappingProvider(new JacksonMappingProvider()).build();
JsonPath.using(cfg).parse(json).set("$[?(@.count == 5)].status", "ok"); Defensive patterns
Strategy: type-guard
Validate before calling
Object v = JsonPath.read(json, operandPath);
if (!(v instanceof String || v instanceof Boolean || v instanceof List || v instanceof Map || v == null)) {
throw new IllegalStateException("Operand type not convertible to ValueNode: " + v.getClass());
} Type guard
boolean isValueNodeConvertible(Object v) {
return v == null || v instanceof String || v instanceof Boolean
|| v instanceof List || v instanceof Map;
} Try / catch
try {
JsonPath.read(json, path);
} catch (JsonPathException e) {
if (e.getMessage().startsWith("Could not convert")) { /* handle type mismatch */ }
} Prevention
- Use a standard MappingProvider (Jackson/Gson) so values map to plain types
- Avoid predicates comparing raw numeric operands on old json-path versions
- Pin json-path to a recent version with numeric ValueNode support
When it happens
Trigger: A filter operand path resolves to an unexpected runtime type — typically a Number (older versions without a numeric branch) or a custom object returned by a MappingProvider — inside a predicate such as [?(@.a.b == 3)] where @.a.b evaluates to an Integer/Double not handled by the conversion chain.
Common situations: Comparing against numeric fields with older json-path versions (numbers were not convertible), using a custom MappingProvider/Configuration that returns domain objects instead of primitives/maps/lists, or documents parsed with a provider producing non-standard types.
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
- e
- JSON path [%s] doesn't match. Expected: %s Actual: %s
- JSON Assert Error: %s Expected: %s Actual: %s
- Document contains the path <%s> but was expected not to.
- InvalidJsonException
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/b89a949bd7ce3554.
Report an issue: GitHub.