spring-projects/spring-ai · error · RuntimeException
Unsupported value type for IN condition. Only supports…
Error message
Unsupported value type for IN condition. Only supports non-empty List of String or Number
What it means
buildInCondition requires the IN operand to be a non-empty List; passing any other value type (single scalar, null, map) or an empty List throws this RuntimeException. Qdrant's matchValues needs a collection of values to match against.
Solutions
- Wrap scalar values in a List: in("genre", List.of("drama")).
- Skip building the IN expression (or the whole filter) when the values collection is empty.
- Coerce single values via Collections.singletonList before passing.
- Guard call sites: if (values != null && !values.isEmpty()) { filter = Filter.builder().in(...) }.
Example fix
// before
Filter.builder().in("genre", selectedGenres).build(); // selectedGenres may be empty
// after
if (selectedGenres != null && !selectedGenres.isEmpty()) {
filter = Filter.builder().in("genre", selectedGenres).build();
} Defensive patterns
Strategy: validation
Validate before calling
static boolean canBuildIn(Object operand) {
return operand instanceof List<?> l && !l.isEmpty();
}
// usage: only add the IN expression when canBuildIn(values) is true Type guard
static boolean isNonEmptyList(Object v) {
return v instanceof List<?> l && !l.isEmpty();
} Try / catch
try {
vectorStore.similaritySearch(req);
} catch (RuntimeException ex) {
if (ex.getMessage() != null && ex.getMessage().contains("Unsupported value type for IN condition")) {
log.warn("IN filter skipped: operand was not a non-empty list");
return vectorStore.similaritySearch(reqWithoutIn);
}
throw ex;
} Prevention
- Wrap single values with List.of(value) before calling in().
- Omit the IN expression entirely when the value collection is empty.
- Guard dynamic filter builders with a non-empty-list check.
When it happens
Trigger: Filter.builder().in("genre", "drama").build() (scalar instead of list) or in("genre", List.of()) (empty list) passed to the Qdrant vector store.
Common situations: Dynamic filter building where the values collection is optional and empty when no filters are selected — callers pass an empty list instead of omitting the expression entirely.
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
- Unsupported value in IN value list. Only supports String or…
- Invalid value type for EQ. Can either be a string or Number
- Invalid value type for NEQ. Can either be a string or Number
- Non AND/OR/NOT expression must have Value right argument!
- Unsupported expression type:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/ea9a2e8aadd9420c.
Report an issue: GitHub.
Appendix: source
Thrown at vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantFilterExpressionConverter.java:189
for (Object valueObj : valueList) {
stringValues.add(valueObj.toString());
}
return io.qdrant.client.ConditionFactory.matchKeywords(identifier, stringValues);
}
else if (firstValue instanceof Number) {
// If the first value is a number, then all values should be numbers
List<Long> longValues = new ArrayList<>();
for (Object valueObj : valueList) {
Long longValue = Long.parseLong(valueObj.toString());
longValues.add(longValue);
}
return io.qdrant.client.ConditionFactory.matchValues(identifier, longValues);
}
else {
throw new RuntimeException("Unsupported value in IN value list. Only supports String or Number");
}
}
throw new RuntimeException(
"Unsupported value type for IN condition. Only supports non-empty List of String or Number");
}
protected Condition buildNInCondition(Key key, Value value) {
if (value.value() instanceof List valueList && !valueList.isEmpty()) {
Object firstValue = valueList.get(0);
String identifier = doKey(key);
if (firstValue instanceof String) {
// If the first value is a string, then all values should be strings
List<String> stringValues = new ArrayList<>();
for (Object valueObj : valueList) {
stringValues.add(valueObj.toString());
}
return io.qdrant.client.ConditionFactory.matchExceptKeywords(identifier, stringValues);
}
else if (firstValue instanceof Number) {View on GitHub (pinned to 98a7beda4f)