spring-projects/spring-ai · error · UnsupportedOperationException
Not supported expression type:
Error message
Not supported expression type:
What it means
getOperationSymbol's default branch throws UnsupportedOperationException for any Filter.ExpressionType not explicitly mapped to a Weaviate GraphQL where-filter operator (EQ, NE, LT, LTE, GT, GTE; IN/NIN are handled separately). It means the expression contains an operator Weaviate's filter syntax cannot express.
Solutions
- Rewrite the filter using supported operators: EQ, NE, LT, LTE, GT, GTE, and IN/NIN (auto-expanded).
- Upgrade spring-ai-weaviate-store in case support for the operator was added in a newer version.
- Pre-check expression types per store and route unsupported filters to a store that supports them or fail fast with a clear message.
Example fix
// before
var expr = new Filter.Expression(Filter.ExpressionType.CONTAINS, new Key("text"), new Value("ai"));
// after
var expr = new Filter.Expression(Filter.ExpressionType.EQ, new Key("text"), new Value("ai")); Defensive patterns
Strategy: validation
Validate before calling
Set<Filter.ExpressionType> WEAVIATE_SUPPORTED = Set.of(EQ, NE, LT, LTE, GT, GTE, IN, NIN); if (!WEAVIATE_SUPPORTED.contains(expr.type())) throw new IllegalArgumentException("Weaviate cannot filter on " + expr.type()); Try / catch
try { vectorStore.similaritySearch(req); } catch (UnsupportedOperationException e) { if (e.getMessage().startsWith("Not supported expression type")) { /* rewrite filter with supported operators */ } else throw e; } Prevention
- Build filters only with EQ/NE/LT/LTE/GT/GTE/IN/NIN for Weaviate
- Re-audit filter operators after Spring AI upgrades
- Fail fast at filter-construction time with a per-store whitelist
When it happens
Trigger: Passing a Filter.Expression with an unmapped type (any operator outside the switch cases) through WeaviateVectorStore similaritySearch or directly into WeaviateFilterExpressionConverter.
Common situations: Newer Spring AI Filter.ExpressionType values appearing after a library upgrade without a matching converter update; generic filter code shared across stores passing operators only some stores support.
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
- The 'IN' operator should have been transformed into chain…
- The 'NIN' operator should have been transformed into chain…
- Expression type not supported for numeric fields
- Expression type not yet implemented. Patches welcome.
- Not allowed filter identifier name: . Consider adding it to…
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/6b5bf44f836be287.
Report an issue: GitHub.
Appendix: source
Thrown at vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/weaviate/WeaviateFilterExpressionConverter.java:122
this.convertOperand(exp.right(), context);
}
}
private String getOperationSymbol(Expression exp) {
return switch (exp.type()) {
case AND -> "operator:And \n";
case OR -> "operator:Or \n";
case EQ -> "operator:Equal \n";
case NE -> "operator:NotEqual \n";
case LT -> "operator:LessThan \n";
case LTE -> "operator:LessThanEqual \n";
case GT -> "operator:GreaterThan \n";
case GTE -> "operator:GreaterThanEqual \n";
case IN -> throw new IllegalStateException(
"The 'IN' operator should have been transformed into chain of OR/EQ expressions.");
case NIN -> throw new IllegalStateException(
"The 'NIN' operator should have been transformed into chain of AND/NEQ expressions.");
default -> throw new UnsupportedOperationException("Not supported expression type:" + exp.type());
};
}
@Override
protected void doKey(Key key, StringBuilder context) {
var identifier = (hasOuterQuotes(key.key())) ? removeOuterQuotes(key.key()) : key.key();
context.append("path:[");
emitJsonValue(withMetaPrefix(identifier), context);
context.append("] \n");
}
public String withMetaPrefix(String identifier) {
if (SYSTEM_IDENTIFIERS.contains(identifier)) {
return identifier;
}
if (this.allowedIdentifierNames.contains(identifier)) {
return this.metaFieldPrefix + identifier;View on GitHub (pinned to 98a7beda4f)