spring-projects/spring-ai · error · IllegalArgumentException
Cannot compare values of types %s and %s
Error message
Cannot compare values of types %s and %s
What it means
compare() throws this when neither null/Number/equals handling applies and at least one side is not Comparable — for example comparing metadata against a Boolean or a Map/List where equality also failed. Unlike error 628 this is not a ClassCastException but a static inability to order the two values.
Source
Thrown at vector-stores/spring-ai-s3-vector-store/src/main/java/org/springframework/ai/vectorstore/s3/S3VectorStoreFilterExpressionEvaluator.java:146
}
if (metaVal instanceof Number n1 && filterVal instanceof Number n2) {
return Double.compare(n1.doubleValue(), n2.doubleValue());
}
if (Objects.equals(metaVal, filterVal)) {
return 0;
}
if (metaVal instanceof Comparable comparable && filterVal instanceof Comparable) {
try {
@SuppressWarnings("unchecked")
int result = comparable.compareTo(filterVal);
return result;
}
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
- Use EQ/NE (or IN/NIN) for non-Comparable values like Booleans, Lists, or objects instead of GT/LT range operators.
- Ensure the metadata field holds a scalar Comparable type (String or Number) consistent with the filter literal type.
- Fix ingestion so structured values (lists/maps) are not stored in fields used for range filtering.
- Pre-filter such documents client-side after retrieval instead of relying on the evaluator's comparison.
Example fix
// before
new Filter.Expression(Filter.ExpressionType.GT, new Filter.Key("enabled"), new Filter.Value(false))
// after
new Filter.Expression(Filter.ExpressionType.EQ, new Filter.Key("enabled"), new Filter.Value(true)) Defensive patterns
Strategy: validation
Validate before calling
static void assertOrderable(Filter.ExpressionType t, Object filterValue) {
if (List.of(GT, GTE, LT, LTE).contains(t) && !(filterValue instanceof Number || filterValue instanceof String || filterValue instanceof Date))
throw new IllegalStateException("Range operators need Number/String/Date, got " + filterValue.getClass());
} Type guard
static boolean orderable(Object v) { return v instanceof Number || v instanceof String || v instanceof Comparable; } Try / catch
try { store.similaritySearch(req); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Cannot compare values of types")) { /* switch to EQ/NE or fix metadata scalar type */ } } Prevention
- Reserve GT/GTE/LT/LTE for Number and String (or date-string) metadata.
- Use EQ/NE/IN/NIN for Booleans, Lists, and structured metadata.
- Avoid storing JSON objects/arrays in fields you plan to range-filter.
When it happens
Trigger: Using an ordering operator (GT/GTE/LT/LTE) or IN/NIN whose element comparison lands here: e.g. metadata field holds a Boolean/List while the filter literal is a String/Number, or metadata contains a nested object that is not Comparable, during S3VectorStore similaritySearch.
Common situations: Ordering filters on boolean fields (booleans are not Comparable against other types here); metadata ingested as JSON arrays/objects then used in range filters; type drift between ingestion and query time.
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
- Cannot compare values of incompatible types %s and %s
- Cannot compare values of types %s and %s
- Cannot compare values of incompatible types %s and %s
- Expected a List value for %s expression but got: %s
- Numeric value must be a Number
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/d9fbeff6a98cad6a.
Report an issue: GitHub.