{"record":{"id":"139fa66bf1c8889f","repo":"spring-projects/spring-ai","slug":"unknown-compare-operator","errorCode":null,"errorMessage":"Unknown compare operator: ","messagePattern":"Unknown compare operator: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/filter/FilterExpressionTextParser.java","lineNumber":284,"sourceCode":"\t\t@Override\n\t\tpublic Filter.Operand visitCompareExpression(FiltersParser.CompareExpressionContext ctx) {\n\t\t\treturn new Filter.Expression(this.convertCompare(ctx.compare().getText()), this.visit(ctx.identifier()),\n\t\t\t\t\tthis.visit(ctx.constant()));\n\t\t}\n\n\t\t@Override\n\t\tpublic Filter.Operand visitIsNullExpression(FiltersParser.IsNullExpressionContext ctx) {\n\t\t\treturn new Filter.Expression(Filter.ExpressionType.ISNULL, this.visit(ctx.identifier()));\n\t\t}\n\n\t\t@Override\n\t\tpublic Filter.Operand visitIsNotNullExpression(FiltersParser.IsNotNullExpressionContext ctx) {\n\t\t\treturn new Filter.Expression(Filter.ExpressionType.ISNOTNULL, this.visit(ctx.identifier()));\n\t\t}\n\n\t\tprivate Filter.ExpressionType convertCompare(String compare) {\n\t\t\tif (!COMP_EXPRESSION_TYPE_MAP.containsKey(compare)) {\n\t\t\t\tthrow new RuntimeException(\"Unknown compare operator: \" + compare);\n\t\t\t}\n\t\t\treturn COMP_EXPRESSION_TYPE_MAP.get(compare);\n\t\t}\n\n\t\t@Override\n\t\tpublic Filter.Operand visitAndExpression(FiltersParser.AndExpressionContext ctx) {\n\t\t\treturn new Filter.Expression(Filter.ExpressionType.AND, this.visit(ctx.left), this.visit(ctx.right));\n\t\t}\n\n\t\t@Override\n\t\tpublic Filter.Operand visitOrExpression(FiltersParser.OrExpressionContext ctx) {\n\t\t\treturn new Filter.Expression(Filter.ExpressionType.OR, this.visit(ctx.left), this.visit(ctx.right));\n\t\t}\n\n\t\t@Override\n\t\tpublic Filter.Operand visitGroupExpression(FiltersParser.GroupExpressionContext ctx) {\n\t\t\treturn new Filter.Group(castToExpression(this.visit(ctx.booleanExpression())));\n\t\t}","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/filter/FilterExpressionTextParser.java#L266-L302","documentation":"The FilterExpressionTextParser converts filter expression DSL text (e.g. \"color == 'red'\") into Filter.Expression trees. convertCompare looks up the comparison operator token in COMP_EXPRESSION_TYPE_MAP; if the token is not a recognized comparison operator (==, !=, >, >=, <, <=, IN, NIN, etc.) it throws this RuntimeException. This means the filter text contained a token the grammar accepted but that is not a valid comparison operator.","triggerScenarios":"Calling new FilterExpressionTextParser().parse(\"price ~~ 10\") or any filter string whose operator token is misspelled or unsupported (e.g. '=', '===', 'eq', '!in'); the token fails the COMP_EXPRESSION_TYPE_MAP lookup in visitCompareExpression -> convertCompare.","commonSituations":"Typos in hand-written filter strings; copying filter syntax from another library (e.g. MongoDB or SQL syntax) that uses different operators; language-model-generated filter text using invented operators.","solutions":["Correct the operator token in the filter expression text to one supported by the DSL: ==, != (also <>), >, >=, <, <=, IN, NIN, NOT, AND, OR","Print/inspect the full filter string; the message appends the offending token so you can locate it","If building filter strings programmatically, prefer constructing Filter.Expression objects directly instead of string parsing","Wrap parse() in try-catch and surface a user-facing validation error with the bad operator"],"exampleFix":"// before\nparser.parse(\"price eq 10\");\n// after\nparser.parse(\"price == 10\");","handlingStrategy":"validation","validationCode":"Set<String> supported = Set.of(\"==\",\"!=\",\">\",\">=\",\"<\",\"<=\",\"IN\",\"NIN\",\"AND\",\"OR\",\"NOT\",\"ISNULL\",\"ISNOTNULL\");\n// validate each operator token of the filter string against 'supported' before calling parse()","typeGuard":null,"tryCatchPattern":"try { filter = new FilterExpressionTextParser().parse(text); }\ncatch (RuntimeException e) { throw new IllegalArgumentException(\"Bad filter operator: \" + e.getMessage(), e); }","preventionTips":["Keep filter strings to the documented DSL operators","Prefer building Filter.Expression objects over string parsing","Validate LLM-generated filter text before parsing"],"tags":["filter-expression","parser","vector-store"],"backgroundTag":"invalid-argument-value","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"}