{"record":{"id":"00c0a1c3ca56eab1","repo":"spring-projects/spring-ai","slug":"can-not-negate-operand-of-type","errorCode":null,"errorMessage":"Can not negate operand of type: ","messagePattern":"Can not negate operand of type: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/filter/FilterHelper.java","lineNumber":102,"sourceCode":"\t\t\t\tcase OR: // NOT(a OR b) = NOT(a) AND NOT(b)\n\t\t\t\t\treturn new Filter.Expression(TYPE_NEGATION_MAP.get(exp.type()), negate(exp.left()),\n\t\t\t\t\t\t\tnegate(exp.right()));\n\t\t\t\tcase EQ: // NOT(e EQ b) = e NE b\n\t\t\t\tcase NE: // NOT(e NE b) = e EQ b\n\t\t\t\tcase GT: // NOT(e GT b) = e LTE b\n\t\t\t\tcase GTE: // NOT(e GTE b) = e LT b\n\t\t\t\tcase LT: // NOT(e LT b) = e GTE b\n\t\t\t\tcase LTE: // NOT(e LTE b) = e GT b\n\t\t\t\t\treturn new Filter.Expression(TYPE_NEGATION_MAP.get(exp.type()), exp.left(), exp.right());\n\t\t\t\tcase IN: // NOT(e IN [...]) = e NIN [...]\n\t\t\t\tcase NIN: // NOT(e NIN [...]) = e IN [...]\n\t\t\t\t\treturn new Filter.Expression(TYPE_NEGATION_MAP.get(exp.type()), exp.left(), exp.right());\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new IllegalArgumentException(\"Unknown expression type: \" + exp.type());\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\"Can not negate operand of type: \" + operand.getClass());\n\t\t}\n\t}\n\n\t/**\n\t * Expands the IN into a semantically equivalent boolean expressions of ORs of EQs.\n\t * Useful for providers that don't provide native IN support.\n\t *\n\t * For example the <pre>\n\t * foo IN [\"bar1\", \"bar2\", \"bar3\"]\n\t * </pre>\n\t *\n\t * expression is equivalent to\n\t *\n\t * <pre>\n\t * {@code foo == \"bar1\" || foo == \"bar2\" || foo == \"bar3\" (e.g. OR(foo EQ \"bar1\" OR(foo EQ \"bar2\" OR(foo EQ \"bar3\")))}\n\t * </pre>\n\t * @param exp input IN expression.\n\t * @param context Output native expression.","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/filter/FilterHelper.java#L84-L120","documentation":"FilterHelper.negate expects a Filter.Expression operand; if it receives any other Filter.Operand (Filter.Value, Filter.Group, etc.) it cannot negate, it throws IllegalArgumentException(\"Can not negate operand of type: \" + operand.getClass()).","triggerScenarios":"Calling FilterHelper.negate(valueOrGroupOperand) where the operand is a Filter.Value (a literal like 'red' or 10) or a Filter.Group instead of a comparison Filter.Expression; reachable from inEx and recursive negate callers.","commonSituations":"Generic filter-rewriting code that iterates an expression tree and calls negate on every node including literal values and groups; providers implementing NOT pushdown for stores without native NOT support.","solutions":["Check operand instanceof Filter.Expression before calling negate() and skip or handle values/groups separately","Negate groups by pushing NOT into their inner expression rather than passing the group itself","Catch IllegalArgumentException and emit an explicit NOT(operand) wrapper as fallback"],"exampleFix":"// before\nFilter.Expression n = FilterHelper.negate(value);\n// after\nif (operand instanceof Filter.Expression exp) { n = FilterHelper.negate(exp); } else { n = new Filter.Expression(ExpressionType.NOT, operand); }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"if (!(operand instanceof Filter.Expression exp)) { /* handle value/group separately */ }","tryCatchPattern":"try { return FilterHelper.negate(operand); }\ncatch (IllegalArgumentException e) { return new Filter.Expression(ExpressionType.NOT, operand); }","preventionTips":["Check operand instanceof Filter.Expression before negate","Skip values and groups when rewriting trees"],"tags":["filter-expression","negation","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}