json-path/JsonPath · error · InvalidPathException
Expected %s but found %s
Error message
Expected %s but found %s
What it means
CharacterIndex.indexOfMatchingCloseChar locates the closing bracket matching an opening one during path parsing. If the character at startPosition is not the expected opening char (openChar), the path text is malformed and InvalidPathException 'Expected X but found Y' is thrown, naming both characters.
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java:92
public int position(){
return position;
}
public int indexOfClosingSquareBracket(int startPosition) {
int readPosition = startPosition;
while (inBounds(readPosition)) {
if(charAt(readPosition) == CLOSE_SQUARE_BRACKET){
return readPosition;
}
readPosition++;
}
return -1;
}
public int indexOfMatchingCloseChar(int startPosition, char openChar, char closeChar, boolean skipStrings, boolean skipRegex) {
if(charAt(startPosition) != openChar){
throw new InvalidPathException("Expected " + openChar + " but found " + charAt(startPosition));
}
int opened = 1;
int readPosition = startPosition + 1;
while (inBounds(readPosition)) {
if (skipStrings) {
char quoteChar = charAt(readPosition);
if (quoteChar == SINGLE_QUOTE || quoteChar == DOUBLE_QUOTE){
readPosition = nextIndexOfUnescaped(readPosition, quoteChar);
if(readPosition == -1){
throw new InvalidPathException("Could not find matching close quote for " + quoteChar + " when parsing : " + charSequence);
}
readPosition++;
}
}
if (skipRegex) {
if (charAt(readPosition) == REGEX) {
readPosition = nextIndexOfUnescaped(readPosition, REGEX);View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Print the full path string and visually verify every [ has a matching ].
- Count brackets/braces in the path before compiling (a simple balance check catches this).
- Fix the malformed segment (add the missing ']' or remove the stray char).
- Escape or quote literal brackets inside filter expressions correctly.
Example fix
// before String path = "$.store.book[?(@.price < 10"; Path p = JsonPath.compile(path); // after String path = "$.store.book[?(@.price < 10)]"; Path p = JsonPath.compile(path);
Defensive patterns
Strategy: validation
Validate before calling
long opens = path.chars().filter(c -> c == '[').count();
long closes = path.chars().filter(c -> c == ']').count();
if (opens != closes) throw new IllegalArgumentException("Unbalanced brackets in path: " + path); Try / catch
try {
Path p = JsonPath.compile(path);
} catch (InvalidPathException e) {
throw new IllegalArgumentException("Malformed JSON path '" + path + "': " + e.getMessage(), e);
} Prevention
- Validate path bracket balance before compiling user-supplied paths.
- Store paths as constants rather than concatenating strings.
- Unit-test every dynamic path template with its substitutions.
When it happens
Trigger: Calling indexOfClosingBracket/indexOfMatchingCloseChar against a path string where the bracket/brace/paren position does not actually hold the expected opening char — e.g. an unclosed or mismatched filter like '$[?(@.a == 1' or '$.store.book[0' during JsonPath.compile/parse.
Common situations: Hand-written JSON path strings with mismatched or missing brackets, braces in filter expressions [?(...)], or programmatically assembled paths where an index segment got dropped.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Could not parse criteria
- Failed to parse ArrayIndexOperation:
- Failed to parse token in ArrayIndexOperation:
- Path must start with '$' or '@'
- Path must not end with a '.
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/b4a5406356ebd376.
Report an issue: GitHub.