spring-projects/spring-ai · error · IllegalArgumentException
Can not negate operand of type:
Error message
Can not negate operand of type:
What it means
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()).
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
Example fix
// before
Filter.Expression n = FilterHelper.negate(value);
// after
if (operand instanceof Filter.Expression exp) { n = FilterHelper.negate(exp); } else { n = new Filter.Expression(ExpressionType.NOT, operand); } Defensive patterns
Strategy: type-guard
Type guard
if (!(operand instanceof Filter.Expression exp)) { /* handle value/group separately */ } Try / catch
try { return FilterHelper.negate(operand); }
catch (IllegalArgumentException e) { return new Filter.Expression(ExpressionType.NOT, operand); } Prevention
- Check operand instanceof Filter.Expression before negate
- Skip values and groups when rewriting trees
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot compare values of incompatible types
- Cannot compare values of incompatible types
- Cannot compare values of types
- Cannot compare values of types
- Expected a List value for
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/00c0a1c3ca56eab1.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/filter/FilterHelper.java:102
case OR: // NOT(a OR b) = NOT(a) AND NOT(b)
return new Filter.Expression(TYPE_NEGATION_MAP.get(exp.type()), negate(exp.left()),
negate(exp.right()));
case EQ: // NOT(e EQ b) = e NE b
case NE: // NOT(e NE b) = e EQ b
case GT: // NOT(e GT b) = e LTE b
case GTE: // NOT(e GTE b) = e LT b
case LT: // NOT(e LT b) = e GTE b
case LTE: // NOT(e LTE b) = e GT b
return new Filter.Expression(TYPE_NEGATION_MAP.get(exp.type()), exp.left(), exp.right());
case IN: // NOT(e IN [...]) = e NIN [...]
case NIN: // NOT(e NIN [...]) = e IN [...]
return new Filter.Expression(TYPE_NEGATION_MAP.get(exp.type()), exp.left(), exp.right());
default:
throw new IllegalArgumentException("Unknown expression type: " + exp.type());
}
}
else {
throw new IllegalArgumentException("Can not negate operand of type: " + operand.getClass());
}
}
/**
* Expands the IN into a semantically equivalent boolean expressions of ORs of EQs.
* Useful for providers that don't provide native IN support.
*
* For example the <pre>
* foo IN ["bar1", "bar2", "bar3"]
* </pre>
*
* expression is equivalent to
*
* <pre>
* {@code foo == "bar1" || foo == "bar2" || foo == "bar3" (e.g. OR(foo EQ "bar1" OR(foo EQ "bar2" OR(foo EQ "bar3")))}
* </pre>
* @param exp input IN expression.
* @param context Output native expression.View on GitHub (pinned to 98a7beda4f)