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

  1. Move the filter up one path level so it applies to the array/object containing the primitive
  2. Verify with a plain read that the pre-filter path resolves to an array or object, not a scalar
  3. Update the path if the document schema changed from array to scalar
  4. 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

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


AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11). Data as JSON: /api/errors/49e4c5808a322060. Report an issue: GitHub.