spring-projects/spring-ai · error · IllegalArgumentException
Expected a List value for %s expression but got: %s
Error message
Expected a List value for %s expression but got: %s
What it means
IN and NIN expressions require the filter value to be a List. The evaluator's asList() throws IllegalArgumentException 'Expected a List value for %s expression but got: %s' when the right-hand operand of IN/NIN is a scalar value.
Source
Thrown at spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/SimpleVectorStoreFilterExpressionEvaluator.java:217
}
if (metaVal instanceof Comparable comparable && filterVal instanceof Comparable) {
try {
return comparable.compareTo(filterVal);
}
catch (ClassCastException ex) {
throw new IllegalArgumentException("Cannot compare values of incompatible types %s and %s"
.formatted(metaVal.getClass().getName(), filterVal.getClass().getName()), ex);
}
}
throw new IllegalArgumentException("Cannot compare values of types %s and %s"
.formatted(metaVal.getClass().getName(), filterVal.getClass().getName()));
}
private List<?> asList(Object value, Filter.Expression expression) {
if (value instanceof List<?> list) {
return list;
}
throw new IllegalArgumentException(
"Expected a List value for %s expression but got: %s".formatted(expression.type(), value));
}
}
View on GitHub (pinned to 98a7beda4f)
Solutions
- Wrap the value in java.util.List: new Filter.Value(List.of("US", "CA")).
- In text filters, use bracketed list syntax: country IN ['US','CA'].
- Guard collection-building code to always produce a List for IN/NIN operands, even for one element.
Example fix
// before
new Filter.Expression(IN, new Filter.Key("country"), new Filter.Value("US"));
// after
new Filter.Expression(IN, new Filter.Key("country"), new Filter.Value(List.of("US"))); Defensive patterns
Strategy: type-guard
Validate before calling
boolean isListValued(Filter.Expression e) {
return e != null && e.right() instanceof Filter.Value v
&& v.value() instanceof java.util.List<?>;
} Type guard
java.util.List<?> requireList(Filter.Value v) { return v.value() instanceof java.util.List<?> l ? l : java.util.List.of(); } Try / catch
try {
vectorStore.similaritySearch(request);
} catch (IllegalArgumentException ex) {
if (ex.getMessage().contains("Expected a List value")) {
// wrap scalar in List.of(...) and rebuild
} else throw ex;
} Prevention
- Always pass List operands for IN/NIN, even for single elements
- Use bracketed list syntax in text filters: field IN ['a','b']
When it happens
Trigger: Building new Filter.Expression(IN, new Filter.Key("country"), new Filter.Value("US")) — a scalar instead of List.of("US", "CA"); or a text filter like "country IN 'US'" missing brackets.
Common situations: Porting SQL IN clauses with a single element and dropping the list; dynamic filters built from a collection that collapsed to a single element; typos in filter string syntax.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Cannot compare values of incompatible types %s and %s
- Cannot compare values of types %s and %s
- Expression of type %s requires a left operand
- Expression of type %s requires a right operand
- Expected a Key operand but got:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/87ca8faa6a31603d.
Report an issue: GitHub.