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

  1. Check operand instanceof Filter.Expression before calling negate() and skip or handle values/groups separately
  2. Negate groups by pushing NOT into their inner expression rather than passing the group itself
  3. 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

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


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)