json-path/JsonPath · error · InvalidPathException
Filter must start with '[?' and end with ']'.
Error message
Filter must start with '[?' and end with ']'.
What it means
After confirming the filter starts with '[' and ends with ']', FilterCompiler trims both and requires the first character to be '?'. A filter like '[(@.price < 10)]' (missing the question mark) fails this check and throws this InvalidPathException. Filters in JsonPath must follow the [?(<expression>)] form.
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java:67
private CharacterIndex filter;
public static Filter compile(String filterString) {
FilterCompiler compiler = new FilterCompiler(filterString);
return new CompiledFilter(compiler.compile());
}
private FilterCompiler(String filterString) {
filter = new CharacterIndex(filterString);
filter.trim();
if (!filter.currentCharIs('[') || !filter.lastCharIs(']')) {
throw new InvalidPathException("Filter must start with '[' and end with ']'. " + filterString);
}
filter.incrementPosition(1);
filter.decrementEndPosition(1);
filter.trim();
if (!filter.currentCharIs('?')) {
throw new InvalidPathException("Filter must start with '[?' and end with ']'. " + filterString);
}
filter.incrementPosition(1);
filter.trim();
if (!filter.currentCharIs('(') || !filter.lastCharIs(')')) {
throw new InvalidPathException("Filter must start with '[?(' and end with ')]'. " + filterString);
}
}
public Predicate compile() {
try {
final ExpressionNode result = readLogicalOR();
filter.skipBlanks();
if (filter.inBounds()) {
throw new InvalidPathException(String.format("Expected end of filter expression instead of: %s",
filter.subSequence(filter.position(), filter.length())));
}
return result;View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Insert '?' after the opening bracket: '[?(...)]' is the required filter form
- Do not confuse script expressions '[(@.length-1)]' with filters; if you want a filter, add '?'
- Re-check the dialect of any copied JSONPath snippet — Goessner-style docs mix '[?(...)]' and other bracket forms
- Validate the path with a quick compile() in a unit test before shipping it in config
Example fix
// before
JsonPath.compile("$..book[(@.price < 10)]");
// after
JsonPath.compile("$..book[?(@.price < 10)]"); Defensive patterns
Strategy: validation
Validate before calling
static boolean isFilterForm(String filter) {
String t = filter == null ? "" : filter.trim();
return t.startsWith("[?") && t.endsWith("]");
} Type guard
boolean hasQuestionMarkFilter(String path) { return path != null && path.matches(".*\\[\\?\\(.*\\)\\].*"); } Try / catch
try {
return JsonPath.compile(path);
} catch (InvalidPathException e) {
if (e.getMessage().contains("must start with '[?'")) {
throw new IllegalArgumentException("Filter missing '?': use [?(...)] in " + path, e);
}
throw e;
} Prevention
- Remember: '[' alone is a script/index expression; filters always need '[?'
- Never confuse Goessner script expressions '[(@.length-1)]' with filter predicates
- Lint JSONPath strings in config at startup by compiling them once
When it happens
Trigger: Passing a filter string like '[(@.x == 1)]' or '[...]' (no '?') to JsonPath.compile(), a path string ending in '[...]' used as a filter predicate, or FilterCompiler.compile via public Path APIs.
Common situations: Confusing script expression syntax '[...]' with filter syntax '[?(...)]' when copying examples from other JSONPath dialects; dropping the '?' during manual editing.
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
- Filter must start with '[' and end with ']'.
- Filter must start with '[?(' and end with ')]'.
- Failed to parse operator
- Filter operator is not supported!
- Could not find matching close quote for %s when parsing : %s
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/d0e0b5647b339187.
Report an issue: GitHub.