spring-projects/spring-ai · error · IllegalArgumentException
Invalid value type for EQ. Can either be a string or Number
Error message
Invalid value type for EQ. Can either be a string or Number
What it means
buildEqCondition translates an EQ comparison into a Qdrant match condition, accepting only String or Number values; anything else (Boolean, null, Date, collection) throws this IllegalArgumentException. Qdrant's match() field conditions only support those scalar types directly.
Source
Thrown at vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantFilterExpressionConverter.java:102
case LT -> buildLtCondition(key, value);
case LTE -> buildLteCondition(key, value);
case IN -> buildInCondition(key, value);
case NIN -> buildNInCondition(key, value);
default -> throw new RuntimeException("Unsupported expression type: " + type);
};
}
protected Condition buildEqCondition(Key key, Value value) {
String identifier = doKey(key);
if (value.value() instanceof String valueStr) {
return io.qdrant.client.ConditionFactory.matchKeyword(identifier, valueStr);
}
else if (value.value() instanceof Number valueNum) {
long lValue = Long.parseLong(valueNum.toString());
return io.qdrant.client.ConditionFactory.match(identifier, lValue);
}
throw new IllegalArgumentException("Invalid value type for EQ. Can either be a string or Number");
}
protected Condition buildNeCondition(Key key, Value value) {
String identifier = doKey(key);
if (value.value() instanceof String valueStr) {
return io.qdrant.client.ConditionFactory.filter(Filter.newBuilder()
.addMustNot(io.qdrant.client.ConditionFactory.matchKeyword(identifier, valueStr))
.build());
}
else if (value.value() instanceof Number valueNum) {
long lValue = Long.parseLong(valueNum.toString());
Condition condition = io.qdrant.client.ConditionFactory.match(identifier, lValue);
return io.qdrant.client.ConditionFactory.filter(Filter.newBuilder().addMustNot(condition).build());
}
throw new IllegalArgumentException("Invalid value type for NEQ. Can either be a string or Number");
View on GitHub (pinned to 98a7beda4f)
Solutions
- Replace boolean equality with a string/int: eq("active", "true") or eq("active", 1), and store metadata accordingly.
- Convert dates to epoch-millis Numbers before filtering.
- For list membership use IN instead of EQ.
- Normalize document metadata on ingestion so filtered fields are always String or Number.
Example fix
// before
Filter.builder().eq("isActive", true).build();
// after
Filter.builder().eq("isActive", "true").build(); Defensive patterns
Strategy: type-guard
Validate before calling
static void checkEqOperand(Object v) {
if (!(v instanceof String) && !(v instanceof Number)) {
throw new IllegalArgumentException("EQ operand must be String or Number, got " + (v == null ? "null" : v.getClass()));
}
} Type guard
static boolean isEqCompatible(Object v) {
return v instanceof String || v instanceof Number;
} Try / catch
try {
vectorStore.similaritySearch(req);
} catch (IllegalArgumentException ex) {
if (ex.getMessage() != null && ex.getMessage().startsWith("Invalid value type for EQ")) {
throw new IllegalArgumentException("Metadata field must be String or Number for EQ", ex);
}
throw ex;
} Prevention
- Never filter on boolean or date metadata with EQ; encode as String/Number at ingestion.
- Validate metadata types when documents are added to the store.
- Document per-field metadata types for your vector-store schema.
When it happens
Trigger: filterExpression(EQ) where the right-hand Value wraps a Boolean (e.g. eq("isActive", true)), null, a date object, or a List — e.g. Filter.builder().eq("active", true).build() passed to the Qdrant store.
Common situations: Document metadata contains booleans or dates; developers write eq("flag", true) expecting Qdrant to handle it. Also common when metadata values are auto-extracted from JSON where a field is an object/array rather than a scalar.
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
- Invalid value type for NEQ. Can either be a string or Number
- Cannot compare values of incompatible types %s and %s
- Cannot compare values of types %s and %s
- Expected a List value for %s expression but got: %s
- Non AND/OR/NOT expression must have Value right argument!
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/fdb237b7901b5541.
Report an issue: GitHub.