json-path/JsonPath · error · InvalidPathException

Could not find matching close for

Error message

Could not find matching close for %s when parsing regex in : %s

What it means

indexOfMatchingCloseChar also supports regex literals inside path filters (a leading slash opens a regex region, detected when skipRegex is true). It uses nextIndexOfUnescaped to locate the closing unescaped slash; if it reaches the end of the input without finding one, it throws InvalidPathException because the regex literal is never terminated.

Solutions

  1. Add the missing closing slash to terminate the regex literal in the path.
  2. Escape any literal slashes inside the regex with a backslash (\/) so they are not mistaken for the terminator.
  3. Pre-test the regex pattern standalone before embedding it into the filter expression.
  4. Use JsonPath.compile() on the generated path early to surface the syntax error at a well-defined point.

Example fix

// before
String path = "$[?(@.url =~ /https://example)]"; // unescaped slashes end the regex early / leave it open
// after
String path = "$[?(@.url =~ /https:\\/\\/example/)]";
Defensive patterns

Strategy: validation

Validate before calling

boolean regexOpen = false;
for (int i = 0; i < path.length(); i++) {
    if (path.charAt(i) == '/' && (i == 0 || path.charAt(i - 1) != '\\')) regexOpen = !regexOpen;
}
if (regexOpen) throw new IllegalArgumentException("Unterminated regex literal in path: " + path);
JsonPath.compile(path);

Try / catch

try {
    return JsonPath.compile(path);
} catch (InvalidPathException e) {
    if (e.getMessage().contains("regex")) {
        throw new IllegalArgumentException("Regex literal in path is not terminated: " + path, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Evaluating a filter path containing a regex pattern like /[.../ or ~regex segments where the closing slash was omitted or escaped incorrectly, e.g. "$[?(@.name =~ /abc)]" with the trailing slash deleted.

Common situations: Hand-written regex filters where the trailing slash is lost during editing; regex patterns built programmatically where the source pattern already contains slashes or escapes; mistaking a regex character class containing a slash for a terminator.

Related errors


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

Appendix: source

Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java:112

        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);
                    if(readPosition == -1){
                        throw new InvalidPathException("Could not find matching close for " + REGEX + " when parsing regex in : " + charSequence);
                    }
                    readPosition++;
                }
            }
            if (charAt(readPosition) == openChar) {
                opened++;
            }
            if (charAt(readPosition) == closeChar) {
                opened--;
                if (opened == 0) {
                    return readPosition;
                }
            }
            readPosition++;
        }
        return -1;
    }

View on GitHub (pinned to 62a4c9f0f6)