json-path/JsonPath · error · InvalidPathException
Filter: %s can not be applied to primitives. Current context
Error message
Filter: %s can not be applied to primitives. Current context is: %s
What it means
InvalidPathException thrown by PredicatePathToken.evaluate when a filter [?(...)] is applied to a primitive (non-array, non-object) value in the current context and the upstream path is definite. Filters only make sense over collections/objects; applying one to a string, number, or boolean is a path misuse.
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicatePathToken.java:67
if (isLeaf()) {
ctx.addResult(currentPath, op, model);
} else {
next().evaluate(currentPath, op, model, ctx);
}
}
} else if (ctx.jsonProvider().isArray(model)){
int idx = 0;
Iterable<?> objects = ctx.jsonProvider().toIterable(model);
for (Object idxModel : objects) {
if (accept(idxModel, ctx.rootDocument(), ctx.configuration(), ctx)) {
handleArrayIndex(idx, currentPath, model, ctx);
}
idx++;
}
} else {
if (isUpstreamDefinite()) {
throw new InvalidPathException(format("Filter: %s can not be applied to primitives. Current context is: %s", toString(), model));
}
}
}
public boolean accept(final Object obj, final Object root, final Configuration configuration, EvaluationContextImpl evaluationContext) {
Predicate.PredicateContext ctx = new PredicateContextImpl(obj, root, configuration, evaluationContext.documentEvalCache());
for (Predicate predicate : predicates) {
try {
if (!predicate.apply(ctx)) {
return false;
}
} catch (InvalidPathException e) {
return false;
}
}
return true;
}View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Move the filter up one path level so it applies to the array/object containing the primitive
- Verify with a plain read that the pre-filter path resolves to an array or object, not a scalar
- Update the path if the document schema changed from array to scalar
- Use a filter on the parent: e.g. "$[?(@.name == 'x')]" instead of "$.name[?(@ == 'x')]"
Example fix
// before JsonPath.read(json, "$.items.name[?(@ == 'widget')]") // after JsonPath.read(json, "$.items[?(@.name == 'widget')]")
Defensive patterns
Strategy: validation
Validate before calling
DocumentContext ctx = JsonPath.parse(json);
Object pre = ctx.read("$.items");
if (!(pre instanceof List) && !(pre instanceof Map)) {
throw new IllegalArgumentException("Filter target is a primitive; apply the filter one level up");
} Try / catch
try {
return JsonPath.read(json, filteredPath);
} catch (InvalidPathException e) {
if (e.getMessage().contains("can not be applied to primitives")) {
throw new IllegalArgumentException("Filter applied to scalar at: " + filteredPath);
}
throw e;
} Prevention
- Place filters on array/object nodes: $[?(@.x == 1)], not $.x[?(@ == 1)]
- Probe the unfiltered path first and assert it resolves to a List/Map
- Re-check filter paths after schema changes that convert arrays to scalars
When it happens
Trigger: Evaluating a path like "$.name[?(@ == 'x')]" where $.name resolves to a string, or applying a filter at a path position that selected a scalar instead of an array/object.
Common situations: Wrong path depth (filter one level too deep into a scalar field), document schema change turning an array into a single value, copy-pasted filter paths applied to the wrong node.
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
- Expected predicate node
- Not enough predicates supplied for filter [] at position
- Can only rename properties in a map
- Can only add to an array
- Can only add properties to a map
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/49e4c5808a322060.
Report an issue: GitHub.