spring-projects/spring-ai · error · IllegalStateException
Unexpected value: {expressionType}
Error message
Unexpected value: {expressionType} What it means
CoherenceFilterExpressionConverter.convert maps Spring AI Filter.Expression types to Coherence Filters and ends with a default branch that throws IllegalStateException for any unsupported type. It is an exhaustiveness guard: the switch only supports EQ, NE, GT, GTE, LT, LTE, IN, NIN, AND, OR.
Source
Thrown at vector-stores/spring-ai-coherence-store/src/main/java/org/springframework/ai/vectorstore/coherence/CoherenceFilterExpressionConverter.java:72
private Filter<?> convert(Expression expression) {
if (expression.type() == ExpressionType.NOT) {
return convert(FilterHelper.negate(expression));
}
Assert.state(expression.right() != null, "expression is expected to have a right operand");
return switch (expression.type()) {
case EQ -> Filters.equal(extractor(expression.left()), value(expression.right()));
case NE -> Filters.notEqual(extractor(expression.left()), value(expression.right()));
case GT -> Filters.greater(extractor(expression.left()), value(expression.right()));
case GTE -> Filters.greaterEqual(extractor(expression.left()), value(expression.right()));
case LT -> Filters.less(extractor(expression.left()), value(expression.right()));
case LTE -> Filters.lessEqual(extractor(expression.left()), value(expression.right()));
case IN -> Filters.in(extractor(expression.left()), ((List) value(expression.right())).toArray());
case NIN ->
Filters.not(Filters.in(extractor(expression.left()), ((List) value(expression.right())).toArray()));
case AND -> Filters.all(convert(expression.left()), convert(expression.right()));
case OR -> Filters.any(convert(expression.left()), convert(expression.right()));
default -> throw new IllegalStateException("Unexpected value: " + expression.type());
};
}
private ValueExtractor extractor(Operand op) {
return new ChainedExtractor(new UniversalExtractor<>("metadata"), new UniversalExtractor<>(((Key) op).key()));
}
private <T> T value(Operand op) {
return (T) ((Value) op).value();
}
}
View on GitHub (pinned to 98a7beda4f)
Solutions
- Rewrite NOT via De Morgan's laws using AND/OR/NE (e.g. not(a.eq(x)) -> a.ne(x)).
- Replace CONTAINS with EQ on scalar fields or IN over known values; move array-membership filtering to application code.
- Extend the converter's switch to map the missing type to Coherence Filters (e.g. Filters.not(...)).
Example fix
// before
Filter.expr("metadata.role").not("admin")
// after
Filter.expr("metadata.role").ne("admin") Defensive patterns
Strategy: validation
Validate before calling
Set<Filter.ExpressionType> OK = Set.of(EQ, NE, GT, GTE, LT, LTE, IN, NIN, AND, OR);
void check(Filter.Expression e) {
if (!OK.contains(e.type())) throw new IllegalArgumentException("Unsupported for Coherence: " + e.type());
if (e.left() instanceof Filter.Expression l) check(l);
if (e.right() instanceof Filter.Expression r) check(r);
} Type guard
boolean coherenceSafe(Filter.Expression e) {
return !(e.type() == NOT || e.type() == CONTAINS || e.type() == CONTAINS_KEY);
} Try / catch
try {
vectorStore.similaritySearch(request);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Unexpected value")) {
// fall back to unfiltered search + client-side filtering
}
} Prevention
- Avoid Filter.not(...) with the Coherence store; rewrite as NE/De Morgan.
- Keep an explicit allow-list of operators per vector store in shared filter-building code.
- Cover all operators in integration tests when adding new filter producers.
When it happens
Trigger: Passing a filter containing NOT or CONTAINS/CONTAINS_KEY (or any type outside the switch) to a Coherence-backed vector store similaritySearch or delete.
Common situations: Using Filter.not(...) built from FilterExpressionTextParser output; porting filters from stores that support contains on arrays; expanding a dynamic filter DSL with new operators not yet mapped.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Expression type %s not yet implemented. Patches welcome.
- Not supported expression type: {expressionType}
- Not supported expression type: {expressionType}
- Not supported expression type: {expressionType}
- Expression type {0} not supported for numeric fields
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/61e41fe441c48e50.
Report an issue: GitHub.