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

If either the metadata value or the filter value is not Comparable, the evaluator cannot perform an ordered/inequality comparison and throws IllegalArgumentException 'Cannot compare values of types'. Unlike error 504, this fires without attempting compareTo — the types simply do not support comparison.

Source

Thrown at spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/SimpleVectorStoreFilterExpressionEvaluator.java:209

		if (filterVal == null) {
			return 1;
		}
		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 {
				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

  1. Ensure every document carries the metadata key used in filters, with a Comparable value (String, Number, Date).
  2. Use IN/NIN instead of scalar comparisons when metadata values are lists.
  3. Validate document metadata completeness at ingestion time.

Example fix

// before
// metadata missing 'year' on some docs; filter uses
new Filter.Expression(GTE, new Filter.Key("year"), new Filter.Value(2020));
// after
// ingest with metadata.put("year", 2020) fallback, or filter
new Filter.Expression(IN, new Filter.Key("year"), new Filter.Value(List.of(2020, 2021)));
Defensive patterns

Strategy: validation

Validate before calling

boolean isComparable(Object v) {
    return v instanceof Comparable<?>;
}

Type guard

<T extends Comparable<T>> boolean canCompare(Object v, Class<T> type) { return type.isInstance(v); }

Try / catch

try {
    vectorStore.similaritySearch(request);
} catch (IllegalArgumentException ex) {
    if (ex.getMessage().startsWith("Cannot compare values of types")) {
        // ensure metadata key exists and is Comparable on all documents
    } else throw ex;
}

Prevention

When it happens

Trigger: Filtering with GT/LT/GTE/LTE (or even EQ) on a metadata value that is null, a List, or a Map — types that are not Comparable.

Common situations: Metadata field missing from a document (null) while the filter uses inequality operators; filtering on list-valued metadata with a scalar comparison.

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


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/30c95eb78e6b3d2e. Report an issue: GitHub.