json-path/JsonPath · error · PathNotFoundException
Expected to find an object with property %s in path %s but f
Error message
Expected to find an object with property %s in path %s but found '%s'. This is not a json object according to the JsonProvider: '%s'.
What it means
During evaluation, PropertyPathToken needs to read a property from a JSON object (Map). If the current model node is not a Map (e.g. an array, string, number, or null), the property cannot be looked up. The library throws PathNotFoundException instead of a hard type error because the path simply does not resolve, unless SUPPRESS_EXCEPTIONS is set or the upstream path is indefinite (in which case it silently returns).
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/path/PropertyPathToken.java:72
}
public boolean multiPropertyIterationCase() {
// Semantics of this case is the same as semantics of ArrayPathToken with INDEX_SEQUENCE operation.
return !isLeaf() && properties.size() > 1;
}
@Override
public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
// Can't assert it in ctor because isLeaf() could be changed later on.
assert onlyOneIsTrueNonThrow(singlePropertyCase(), multiPropertyMergeCase(), multiPropertyIterationCase());
if (!ctx.jsonProvider().isMap(model)) {
if (!isUpstreamDefinite()
|| ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) {
return;
} else {
String m = model == null ? "null" : model.getClass().getName();
throw new PathNotFoundException(String.format(
"Expected to find an object with property %s in path %s but found '%s'. " +
"This is not a json object according to the JsonProvider: '%s'.",
getPathFragment(), currentPath, m, ctx.configuration().jsonProvider().getClass().getName()));
}
}
if (singlePropertyCase() || multiPropertyMergeCase()) {
handleObjectProperty(currentPath, model, ctx, properties);
return;
}
assert multiPropertyIterationCase();
final List<String> currentlyHandledProperty = new ArrayList<String>(1);
currentlyHandledProperty.add(null);
for (final String property : properties) {
currentlyHandledProperty.set(0, property);
handleObjectProperty(currentPath, model, ctx, currentlyHandledProperty);
}View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Fix the path so it matches the actual document shape (add array iteration [*] or filters where the node is an array)
- Validate/inspect the document before reading (e.g. read the parent node and check it is a Map)
- Add Option.SUPPRESS_EXCEPTIONS to the Configuration if a miss is acceptable and null/absence should be tolerated
- Use definitive(...) or JsonPath.parse(...).read with default value handling (read(path, default)) for optional fields
Example fix
// before String name = JsonPath.read(json, "$.user.name"); // throws if user is a string/null // after Object user = JsonPath.read(json, "$.user"); String name = (user instanceof Map) ? JsonPath.read(json, "$.user.name") : null;
Defensive patterns
Strategy: type-guard
Validate before calling
Object parent = JsonPath.read(json, "$.user");
if (!(parent instanceof Map)) throw new IllegalStateException("$.user is not an object"); Type guard
boolean isObject(Object o) { return o instanceof Map<?, ?>; } Try / catch
try {
return JsonPath.read(json, "$.user.name");
} catch (PathNotFoundException e) {
return null; // or default value
} Prevention
- Align paths with the actual document schema; inspect samples first
- Use Option.SUPPRESS_EXCEPTIONS for optional lookups
- Add contract tests asserting API response shape
- Prefer read(path, defaultValue) for optional fields
When it happens
Trigger: Evaluating $.foo.bar where $.foo resolves to a string/number/array/null instead of an object; calling JsonPath.read on a document whose structure differs from the expected schema; using definite paths against documents where an intermediate node is a primitive.
Common situations: API responses that changed shape (field is now a scalar or missing); reading paths like $.user.name when user is null; querying arrays with object-property paths without the correct [?] filter or ['..'] wildcard; mismatched schema between producer and consumer services.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Can only rename properties in a map
- Can only add to an array
- Can only add properties to a map
- Failed to evaluate exists expression
- The path is null
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/8b2436425a7d3ad8.
Report an issue: GitHub.