spring-projects/spring-ai · error · IllegalArgumentException
Expected a List, but got:
Error message
Expected a List, but got:
What it means
PgVectorFilterExpressionConverter.convertToConditions only supports IN/NOTIN (NIN) filter expressions whose right operand is a Filter.Value wrapping a java.util.List. If the right side is a single value (e.g. Filter.eq-style value passed where an IN was expected, or a non-collection value), the cast to List would fail, so the converter throws this IllegalArgumentException up front.
Source
Thrown at vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/pgvector/PgVectorFilterExpressionConverter.java:83
else {
this.convertOperand(expression.left(), context);
context.append(getOperationSymbol(expression));
this.convertOperand(expression.right(), context);
}
}
private void handleIn(Expression expression, StringBuilder context) {
context.append("(");
convertToConditions(expression, context);
context.append(")");
}
private void convertToConditions(Expression expression, StringBuilder context) {
Assert.state(expression.right() != null, "expression should have a right operand");
Filter.Value right = (Filter.Value) expression.right();
Object value = right.value();
if (!(value instanceof List)) {
throw new IllegalArgumentException("Expected a List, but got: " + value.getClass().getSimpleName());
}
List<Object> values = (List) value;
for (int i = 0; i < values.size(); i++) {
this.convertOperand(expression.left(), context);
context.append(" == ");
this.doSingleValue(normalizeDateString(values.get(i)), context);
if (i < values.size() - 1) {
context.append(" || ");
}
}
}
private void handleNotIn(Expression expression, StringBuilder context) {
context.append("!(");
convertToConditions(expression, context);
context.append(")");
}
View on GitHub (pinned to 98a7beda4f)
Solutions
- Wrap the right-hand operand in a List: Filter.in("country", List.of("US","DE")) instead of a single value.
- Use Filter.eq / Filter.ne for single-value comparisons instead of in/nin.
- Check the Filter.Expression you built: expression.right() must be a Filter.Value whose value() instanceof List.
Example fix
// before
Expression e = new Expression(IN, "country", new Value("US"));
// after
Expression e = new Expression(IN, "country", new Value(List.of("US", "DE"))); Defensive patterns
Strategy: validation
Validate before calling
if (!(expr instanceof Filter.Expression fe && fe.right() instanceof Filter.Value v && v.value() instanceof List)) {
throw new IllegalArgumentException("IN/NIN requires a List value");
} Type guard
static boolean isInWithListValue(Expression e) {
return e instanceof Filter.Expression fe
&& fe.right() instanceof Filter.Value v
&& v.value() instanceof List<?>;
} Try / catch
try {
String sql = converter.convertExpression(expr);
} catch (IllegalArgumentException e) {
// log offending expression; fix filter construction
} Prevention
- Always use Filter.in(key, List.of(...)) with a collection.
- Use eq/ne for single values rather than in with scalars.
- Unit-test custom Filter.Expression trees before production use.
When it happens
Trigger: Building a PgVectorStore filter like Filter.in("country", ...) indirectly but with a single non-List value on the right side — e.g. using Filter.in with a scalar, or a custom Expression whose right() is a Value holding a String/Number instead of a List.
Common situations: Hand-constructing Filter.Expression trees instead of using the Filter expression DSL; migrating filters from another vector store whose converter accepted scalars for IN; a typo where eq was intended but in semantics got built.
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
- Not supported expression type:
- Single parameter must be of type ElicitRequest:
- First parameter must be of type Double or double: {method.ge
- Second parameter must be of type String: {method.getName()}
- Third parameter must be of type String: {method.getName()} i
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/5f0e997527efd559.
Report an issue: GitHub.