spring-projects/spring-ai · error · FilterExpressionParseException
FilterExpressionParseException (message aggregated from…
Error message
FilterExpressionParseException (message aggregated from parse error listener)
What it means
FilterExpressionTextParser.parse() converts a filter expression string into a Filter.Expression using an ANTLR parser. On ParseCancellationException, it aggregates messages collected by its error listener and throws FilterExpressionParseException with the joined message and root cause. This is the standard failure for syntactically invalid filter strings.
Solutions
- Fix the filter string syntax to match the Spring AI filter grammar (==, !=, >, IN, AND, OR, brackets).
- Use FilterExpressionBuilder programmatic API to avoid string parsing entirely.
- Catch FilterExpressionParseException and surface the aggregated error message to identify the offending token.
- Call clearCache()/verify cache behavior if a previously cached bad expression persists.
Example fix
// before String filter = "color == green"; // unquoted value // after String filter = "color == 'green'";
Defensive patterns
Strategy: try-catch
Validate before calling
boolean looksParseable(String f) {
return f != null
&& f.chars().filter(c -> c == '\'' || c == '"').count() % 2 == 0
&& f.chars().filter(c -> c == '[').count() == f.chars().filter(c -> c == ']').count();
} Try / catch
try {
Filter.Expression f = new FilterExpressionTextParser().parse(filterText);
request = SearchRequest.builder().filterExpression(f).build();
} catch (FilterExpressionParseException ex) {
log.warn("Bad filter '{}': {}", filterText, ex.getMessage());
// fall back to unfiltered search or reject input
} Prevention
- Test filter strings against the documented grammar before shipping
- Prefer programmatic FilterExpressionBuilder for user-derived filters
- Validate quotes and brackets are balanced in generated filters
When it happens
Trigger: Passing a malformed filter string to SearchRequest.builder().filterExpression("..."): unbalanced quotes/brackets, unknown tokens, invalid operators (e.g. "color eq 'green'" lowercase), missing operands.
Common situations: Filters built by string concatenation from user input; locale/formatting mistakes; typos in field names or operators; upgrading Spring AI and using removed syntax.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Cannot compare values of incompatible types
- Cannot compare values of types
- Expected a Key operand but got:
- Expected a List value for
- Expected a Value operand but got:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/ed24820ffee61623.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/filter/FilterExpressionTextParser.java:162
parser.removeErrorListeners();
this.errorListener.errorMessages.clear();
parser.addErrorListener(this.errorListener);
if (this.errorHandler != null) {
parser.setErrorHandler(this.errorHandler);
}
var filterExpressionVisitor = new FilterExpressionVisitor();
try {
Filter.Operand operand = filterExpressionVisitor.visit(parser.where());
var filterExpression = filterExpressionVisitor.castToExpression(operand);
this.cache.putIfAbsent(textFilterExpression, filterExpression);
return filterExpression;
}
catch (ParseCancellationException e) {
var msg = String.join("", this.errorListener.errorMessages);
var rootCause = NestedExceptionUtils.getRootCause(e);
throw new FilterExpressionParseException(msg, rootCause);
}
}
public void clearCache() {
this.cache.clear();
}
/** For testing only */
Map<String, Filter.Expression> getCache() {
return this.cache;
}
public static class FilterExpressionParseException extends RuntimeException {
public FilterExpressionParseException(String message, @Nullable Throwable cause) {
super(message, cause);
}
View on GitHub (pinned to 98a7beda4f)