json-path/JsonPath · error · JsonPathException
Could not determine value type
Error message
Could not determine value type
What it means
ValueNode.toValueNode(Object o) converts an arbitrary Java object into a ValueNode for filter evaluation (strings, characters, numbers, booleans, Patterns, OffsetDateTimes are supported). When the object's type is unrecognized, it throws JsonPathException("Could not determine value type"). This happens when a filter operand or evaluated value is a Java type the converter does not handle, such as Map, List, raw Date, UUID, byte[], or custom POJOs.
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java:178
//----------------------------------------------------
//
// Factory methods
//
//----------------------------------------------------
public static ValueNode toValueNode(Object o){
if(o == null) return NULL_NODE;
if(o instanceof ValueNode) return (ValueNode)o;
if(o instanceof Class) return createClassNode((Class)o);
else if(isPath(o)) return new PathNode(o.toString(), false, false);
else if(isJson(o)) return createJsonNode(o.toString());
else if(o instanceof String) return createStringNode(o.toString(), true);
else if(o instanceof Character) return createStringNode(o.toString(), false);
else if(o instanceof Number) return createNumberNode(o.toString());
else if(o instanceof Boolean) return createBooleanNode(o.toString());
else if(o instanceof Pattern) return createPatternNode((Pattern)o);
else if (o instanceof OffsetDateTime) return createOffsetDateTimeNode(o.toString()); //workaround for issue: https://github.com/json-path/JsonPath/issues/613
else throw new JsonPathException("Could not determine value type");
}
public static StringNode createStringNode(CharSequence charSequence, boolean escape){
return new StringNode(charSequence, escape);
}
public static ClassNode createClassNode(Class<?> clazz){
return new ClassNode(clazz);
}
public static NumberNode createNumberNode(CharSequence charSequence){
return new NumberNode(charSequence);
}
public static BooleanNode createBooleanNode(CharSequence charSequence){
return Boolean.parseBoolean(charSequence.toString()) ? TRUE : FALSE;
}View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Convert the value to a supported type before evaluation: OffsetDateTime for dates, String/Number/Boolean/Pattern/Character
- Convert Maps and Lists to a parsed document via JsonPath.parse()/Configuration before using them as operands
- Use the #613 workaround contract: pass OffsetDateTime (not java.util.Date) for datetime comparisons
- Catch JsonPathException around evaluation and implement custom conversion logic for your types
Example fix
// before
Date d = new Date();
filter.where("$.created lt " + d); // java.util.Date -> JsonPathException
// after
OffsetDateTime d = OffsetDateTime.now();
filter.where("$.created lt " + d); // supported type Defensive patterns
Strategy: validation
Validate before calling
static void assertSupportedOperand(Object o) {
if (!(o instanceof String || o instanceof Character || o instanceof Number || o instanceof Boolean || o instanceof Pattern || o instanceof OffsetDateTime))
throw new IllegalArgumentException("Unsupported filter operand type: " + o.getClass());
} Type guard
static boolean isConvertibleToValueNode(Object o) { return o instanceof String || o instanceof Character || o instanceof Number || o instanceof Boolean || o instanceof Pattern || o instanceof OffsetDateTime; } Try / catch
try {
return JsonPath.parse(json).read("$.items[?(@.x in [" + operand + "])]");
} catch (JsonPathException e) {
if (e.getMessage().contains("Could not determine value type")) {
// convert the operand to a supported type and retry
return evaluateWithConvertedOperand(json);
}
throw e;
} Prevention
- Pass only String/Character/Number/Boolean/Pattern/OffsetDateTime as filter operands
- Convert java.util.Date to OffsetDateTime before filtering
- Parse Maps/Lists into documents with JsonPath.parse before using them as operands
- Convert UUID/enums/custom types to String before embedding in filters
When it happens
Trigger: Passing an unsupported Java object as a filter operand or as a document value that needs conversion: e.g. supplying a java.util.Date or java.util.UUID in a filter parameter, a List/Map not converted by the caller, or a custom type reaching toValueNode during evaluation of a parameterized filter like $.items[?(@.x in ${list})].
Common situations: Using java.util.Date instead of OffsetDateTime for date filters (pre-#613 types unsupported); passing Java 8+ types like UUID or enums; supplying collections that should have been pre-parsed via JsonPath.parse; custom JSON providers producing wrapper objects that leak into toValueNode.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Criteria can not be null
- Could not parse criteria
- Criteria build exception. Complete on criteria before defini
- Expected string node
- Expected boolean node
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/5d7d2ec27ec51789.
Report an issue: GitHub.