json-path/JsonPath · error · InvalidPathException
Expected '?' but found
Error message
Expected '?' but found
What it means
InvalidPathException thrown by readPlaceholderToken when a token inside a filter's placeholder expression is not the literal '?'. Positional predicate placeholders must be exactly '?'; anything else (a name, number, or typo) is rejected because the compiler cannot map it to a predicate.
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java:437
int expressionEndIndex = path.nextIndexOf(expressionBeginIndex, CLOSE_SQUARE_BRACKET);
if (expressionEndIndex == -1) {
return false;
}
String expression = path.subSequence(expressionBeginIndex, expressionEndIndex).toString();
String[] tokens = expression.split(",");
if (filterStack.size() < tokens.length) {
throw new InvalidPathException("Not enough predicates supplied for filter [" + expression + "] at position " + path.position());
}
Collection<Predicate> predicates = new ArrayList<Predicate>();
for (String token : tokens) {
token = token != null ? token.trim() : null;
if (!"?".equals(token == null ? "" : token)) {
throw new InvalidPathException("Expected '?' but found " + token);
}
predicates.add(filterStack.pop());
}
appender.appendPathToken(PathTokenFactory.createPredicatePathToken(predicates));
path.setPosition(expressionEndIndex + 1);
return path.currentIsTail() || readNextToken(appender);
}
//
// [?(...)]
//
private boolean readFilterToken(PathTokenAppender appender) {
if (!path.currentCharIs(OPEN_SQUARE_BRACKET) && !path.nextSignificantCharIs(BEGIN_FILTER)) {
return false;
}View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Replace the invalid token with a plain '?' for positional predicates
- Use inline filter syntax [?(@.price < 10)] instead of placeholders if you don't want external predicates
- Trim and inspect the filter expression — the offending token is printed in the message
Example fix
// before JsonPath.read(json, "$..book[? @.x]") // after JsonPath.read(json, "$..book[?(@.x)]")
Defensive patterns
Strategy: validation
Validate before calling
static boolean validPlaceholderFilter(String filterExpr) {
// filterExpr is the text inside [ ], e.g. "?" or "? , ?"
if (filterExpr.trim().isEmpty()) return false;
for (String tok : filterExpr.split(",")) {
if (!"?".equals(tok.trim())) return false;
}
return true;
} Try / catch
try {
return JsonPath.read(json, path);
} catch (InvalidPathException e) {
if (e.getMessage().startsWith("Expected '?'")) {
throw new IllegalArgumentException("Bad placeholder token in path: " + path);
}
throw e;
} Prevention
- Remember positional placeholders are exactly '?'; inline filters use [?(@ ...)] syntax — don't mix them
- Trim tokens before validating; extra words inside [ ] are rejected
- Prefer inline filter expressions to avoid placeholder/token mismatches
When it happens
Trigger: Compiling a path like "$..book[?x]" or "$[ ?isTrue ]" where the filter bracket contains a placeholder token that is not exactly '?'.
Common situations: Typos such as '??' fragments, whitespace-embedded tokens after splitting on commas, confusion with inline filter syntax [?(@.x == 1)] vs positional [?].
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Not enough predicates supplied for filter [] at position
- Could not find matching close quote for %s when parsing : %s
- Could not find matching close for %s when parsing regex in :
- Expected character: %c
- Filter must start with '[' and end with ']'.
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/012f0d2428f27b04.
Report an issue: GitHub.