{"record":{"id":"d485839ba5445e88","repo":"spring-projects/spring-ai","slug":"invalid-expression-d48583","errorCode":null,"errorMessage":"Invalid expression: ","messagePattern":"Invalid expression: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/filter/FilterExpressionTextParser.java","lineNumber":325,"sourceCode":"\t\t}\n\n\t\t@Override\n\t\tpublic Filter.Operand visitLongConstant(FiltersParser.LongConstantContext ctx) {\n\t\t\tString text = ctx.getText();\n\t\t\t// Remove the trailing 'l' or 'L'\n\t\t\tlong value = Long.parseLong(text.substring(0, text.length() - 1));\n\t\t\treturn new Filter.Value(value);\n\t\t}\n\n\t\tpublic Filter.Expression castToExpression(Filter.Operand expression) {\n\t\t\tif (expression instanceof Filter.Group group) {\n\t\t\t\t// Remove the top-level grouping.\n\t\t\t\treturn group.content();\n\t\t\t}\n\t\t\telse if (expression instanceof Filter.Expression exp) {\n\t\t\t\treturn exp;\n\t\t\t}\n\t\t\tthrow new RuntimeException(\"Invalid expression: \" + expression);\n\t\t}\n\n\t}\n\n\tpublic static class DescriptiveErrorListener extends BaseErrorListener {\n\n\t\tpublic static final DescriptiveErrorListener INSTANCE = new DescriptiveErrorListener();\n\n\t\tpublic final List<String> errorMessages = new CopyOnWriteArrayList<>();\n\n\t\t@Override\n\t\tpublic void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,\n\t\t\t\tString msg, RecognitionException e) {\n\n\t\t\tString sourceName = recognizer.getInputStream().getSourceName();\n\n\t\t\tvar errorMessage = String.format(\"Source: %s, Line: %s:%s, Error: %s\", sourceName, line, charPositionInLine,\n\t\t\t\t\tmsg);","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/filter/FilterExpressionTextParser.java#L307-L343","documentation":"castToExpression converts the parse result into a Filter.Expression. The grammar may yield a Filter.Group or a raw Filter.Value at the top level; only Filter.Expression (and an ungrouped inner expression) are accepted. If the parsed operand is neither, the parser throws RuntimeException(\"Invalid expression: \" + expression). It is thrown from the parser's tree-cast step, meaning the input parsed but has a shape the API cannot return.","triggerScenarios":"Parsing a filter string whose result is a bare value or an empty/odd group rather than a boolean expression, e.g. parse(\"'red'\") or a string that only produces a group node the cast cannot unwrap, via visitGroupExpression -> castToExpression.","commonSituations":"LLM-generated filter strings that are just a literal value; partially deleted filter text; passing a search-term string where a boolean filter expression is expected.","solutions":["Provide a complete boolean filter expression (identifier OP value, optionally combined with AND/OR/NOT) instead of a bare literal or value","Check the input string is non-empty and syntactically a full expression, e.g. \"country == 'BG'\"","Catch RuntimeException from parse() and show a filter-syntax validation message to the user","Build the Filter.Expression tree programmatically to avoid string-parse ambiguity"],"exampleFix":"// before\nparser.parse(\"'red'\");\n// after\nparser.parse(\"color == 'red'\");","handlingStrategy":"validation","validationCode":"if (filterText == null || filterText.isBlank() || !filterText.matches(\".*[<>=!].*\")) throw new IllegalArgumentException(\"Filter must be a full expression\");","typeGuard":null,"tryCatchPattern":"try { filter = parser.parse(text); }\ncatch (RuntimeException e) { log.warn(\"Invalid filter expression: {}\", text, e); filter = null; }","preventionTips":["Always include an operator and identifier in filter text","Never pass bare literals as filters","Unit-test filter strings you generate"],"tags":["filter-expression","parser","vector-store"],"backgroundTag":"invalid-argument-format","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}