spring-projects/spring-ai · error · IllegalArgumentException
Expression of type %s requires a left operand
Error message
Expression of type %s requires a left operand
What it means
The evaluator's left() accessor throws IllegalArgumentException when a Filter.Expression has no left operand but the expression type requires one. All operators evaluated by evaluateExpression (AND, OR, NOT, comparisons, IN/NIN, ISNULL/ISNOTNULL) need a left side, so a null left operand is treated as a malformed filter.
Source
Thrown at vector-stores/spring-ai-s3-vector-store/src/main/java/org/springframework/ai/vectorstore/s3/S3VectorStoreFilterExpressionEvaluator.java:84
case IN -> {
Object metaVal = metadataValue(left(expression), metadata);
List<?> list = asList(filterValue(right(expression)), expression);
yield list.stream().anyMatch(item -> compare(metaVal, item) == 0);
}
case NIN -> {
Object metaVal = metadataValue(left(expression), metadata);
List<?> list = asList(filterValue(right(expression)), expression);
yield list.stream().noneMatch(item -> compare(metaVal, item) == 0);
}
case ISNULL -> metadataValue(left(expression), metadata) == null;
case ISNOTNULL -> metadataValue(left(expression), metadata) != null;
};
}
private Filter.Operand left(Filter.Expression expression) {
Filter.Operand left = expression.left();
if (left == null) {
throw new IllegalArgumentException(
"Expression of type %s requires a left operand".formatted(expression.type()));
}
return left;
}
private Filter.Operand right(Filter.Expression expression) {
Filter.Operand right = expression.right();
if (right == null) {
throw new IllegalArgumentException(
"Expression of type %s requires a right operand".formatted(expression.type()));
}
return right;
}
private @Nullable Object metadataValue(Filter.Operand operand, Map<String, Object> metadata) {
if (operand instanceof Filter.Key key) {
String k = key.key();
if (k.length() >= 2View on GitHub (pinned to 98a7beda4f)
Solutions
- For NOT, place the negated expression as the LEFT operand: new Filter.Expression(NOT, groupOrExpression, null).
- Use the Filter builder/expr helper to construct expressions so operand placement is correct.
- Before evaluation, assert expression.left() != null for every node you build programmatically.
- Catch IllegalArgumentException around similaritySearch and inspect the type named in the message.
Example fix
// before
new Filter.Expression(Filter.ExpressionType.NOT, null, Filter.group(eq("a", 1)))
// after
new Filter.Expression(Filter.ExpressionType.NOT, Filter.group(eq("a", 1)), null) Defensive patterns
Strategy: validation
Validate before calling
static void requireLeft(Filter.Expression e) { if (e.left() == null) throw new IllegalStateException("Expression " + e.type() + " needs a left operand"); } Type guard
static boolean hasLeft(Filter.Expression e) { return e.left() != null; } Try / catch
try { store.similaritySearch(req); } catch (IllegalArgumentException e) { if (e.getMessage().endsWith("requires a left operand")) { /* fix NOT operand placement */ } } Prevention
- Put NOT's negated child on the LEFT operand slot.
- Assert non-null operands on every node of hand-built filter trees.
- Prefer Filter.expr(...) parsing over manual expression construction.
When it happens
Trigger: Constructing a Filter.Expression with a null left operand — most typically a NOT expression built as new Filter.Expression(NOT, null, child) — then evaluating it via S3VectorStore similaritySearch post-filtering.
Common situations: NOT misuse: some filter models put the negated child on the right, but this evaluator reads NOT's child from the left; manual expression construction; migrating filters from stores where NOT carries its operand on the right.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Unsupported operator:
- Expression of type %s requires a right operand
- Not supported expression type:
- Unsupported Number type:
- Unsupported operand type:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/59a2922bcb870ef1.
Report an issue: GitHub.