{"record":{"id":"7357b55848522373","repo":"json-path/JsonPath","slug":"filter-must-start-with-and-end-with-7357b5","errorCode":null,"errorMessage":"Filter must start with '[?(' and end with ')]'. ","messagePattern":"Filter must start with '\\[\\?\\(' and end with '\\)\\]'\\. ","errorType":"exception","errorClass":"InvalidPathException","httpStatus":null,"severity":"error","filePath":"json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java","lineNumber":72,"sourceCode":"        return new CompiledFilter(compiler.compile());\n    }\n\n    private FilterCompiler(String filterString) {\n        filter = new CharacterIndex(filterString);\n        filter.trim();\n        if (!filter.currentCharIs('[') || !filter.lastCharIs(']')) {\n            throw new InvalidPathException(\"Filter must start with '[' and end with ']'. \" + filterString);\n        }\n        filter.incrementPosition(1);\n        filter.decrementEndPosition(1);\n        filter.trim();\n        if (!filter.currentCharIs('?')) {\n            throw new InvalidPathException(\"Filter must start with '[?' and end with ']'. \" + filterString);\n        }\n        filter.incrementPosition(1);\n        filter.trim();\n        if (!filter.currentCharIs('(') || !filter.lastCharIs(')')) {\n            throw new InvalidPathException(\"Filter must start with '[?(' and end with ')]'. \" + filterString);\n        }\n    }\n\n    public Predicate compile() {\n        try {\n             final ExpressionNode result = readLogicalOR();\n             filter.skipBlanks();\n             if (filter.inBounds()) {\n                 throw new InvalidPathException(String.format(\"Expected end of filter expression instead of: %s\",\n                         filter.subSequence(filter.position(), filter.length())));\n             }\n\n             return result;\n        } catch (InvalidPathException e){\n            throw e;\n        } catch (Exception e) {\n            throw new InvalidPathException(\"Failed to parse filter: \" + filter + \", error on position: \" + filter.position() + \", char: \" + filter.currentChar());\n        }","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/json-path/JsonPath/blob/62a4c9f0f65ba3f625aa0867d64c528ba72d09ec/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java#L54-L90","documentation":"After '[?' is accepted, FilterCompiler trims and requires the next character to be '(' and the last character of the trimmed string to be ')'. Filters must be fully parenthesized: '[?(<expression>)]'. Unbalanced or missing parentheses throw this InvalidPathException.","triggerScenarios":"A filter like '[?@.price < 10)]' or '[?(@.price < 10]' (missing closing paren or bracket), produced by string concatenation where only one side of the predicate wrapper was added.","commonSituations":"Dynamic query building where '(' was added but ')]' truncated; copying a partial expression from a log; nested parentheses miscounted so the final ')' is missing.","solutions":["Ensure the predicate is wrapped in a balanced parenthesis pair: '[?(' + expr + ')]'","Count parentheses in nested logical expressions, e.g. '[?(@.a && (@.b || @.c))]'","When building dynamically, encapsulate in one helper that always emits the full '[?(...)]' wrapper","Compile the path in a test to catch the truncation early"],"exampleFix":"// before\nJsonPath.compile(\"$..book[?@.price < 10]\");\n// after\nJsonPath.compile(\"$..book[?(@.price < 10)]\");","handlingStrategy":"validation","validationCode":"static boolean isParenthesizedFilter(String filter) {\n    String t = filter == null ? \"\" : filter.trim();\n    return t.startsWith(\"[?(\" ) && t.endsWith(\")]\");\n}","typeGuard":"boolean balancedParens(String expr) {\n    int d = 0;\n    for (char c : expr.toCharArray()) { if (c=='(') d++; if (c==')') d--; if (d<0) return false; }\n    return d == 0;\n}","tryCatchPattern":"try {\n    return JsonPath.compile(path);\n} catch (InvalidPathException e) {\n    throw new IllegalArgumentException(\"Filter must be '[?(...)]', got: \" + path, e);\n}","preventionTips":["Wrap every predicate in a balanced '( ... )' pair inside '[?...]','...']","For nested boolean logic, count parentheses or build with Criteria API which manages grouping","Avoid manual string splicing of predicate fragments"],"tags":["json-path","filter-syntax","invalid-path"],"backgroundTag":"invalid-argument-format","analyzedSha":"62a4c9f0f65ba3f625aa0867d64c528ba72d09ec","analyzedAt":"2026-09-11T11:36:00.448Z","contentChangedAt":"2026-09-11T11:36:00.448Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}