`FilterExpressionTextParser` shares mutable error state across instances
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
Research direction
Start with FilterExpressionTextParser, its constructor, parse() flow, and DescriptiveErrorListener.INSTANCE usage. Use the provided JUnit regression test as the first check, then verify that separate parser instances collect diagnostics independently during concurrent invalid parses.
Written by the indexing model from the issue text.
Description
Bug description
FilterExpressionTextParser assigns the same mutable DescriptiveErrorListener.INSTANCE to every parser instance.
Each call to parse() clears, modifies, and reads the listener's shared errorMessages list. Concurrent parsing through separate parser instances can therefore interfere with diagnostic collection performed by another invocation.
CopyOnWriteArrayList makes individual list operations thread-safe, but it does not isolate the compound clear → parse → join sequence.
If the maintainers agree that this is a bug, I would be happy to work on the fix and submit a pull request with regression tests.
Environment
- Spring AI:
2.0.1-SNAPSHOT - Tested artifact:
spring-ai-vector-store-2.0.1-20260808.133500-105.jar - Java: 17.0.17
- ANTLR runtime: 4.13.2
- Vector store: none required
Steps to reproduce
- Create two separate
FilterExpressionTextParserinstances. - Retrieve the
errorListenerassigned to each instance. - Observe that both parser instances use the same listener.
- Run invalid parse operations concurrently and observe that both calls operate
on the sameerrorMessagescollection.
Relevant implementation:
public FilterExpressionTextParser(ANTLRErrorStrategy handler) {
this.errorListener = DescriptiveErrorListener.INSTANCE;
this.errorHandler = handler;
}
parser.removeErrorListeners();
this.errorListener.errorMessages.clear();
parser.addErrorListener(this.errorListener);
var msg = String.join("", this.errorListener.errorMessages);
Expected behavior
Each parser invocation, or at least each parser instance, should collect its syntax error messages independently. Concurrent parsing should not clear or modify diagnostics belonging to another invocation.
Minimal Complete Reproducible example
The following JUnit test fails because both parser instances receive the same
mutable error listener:
import java.lang.reflect.Field;
import org.junit.jupiter.api.Test;
import org.springframework.ai.vectorstore.filter.FilterExpressionTextParser;
import static org.assertj.core.api.Assertions.assertThat;
class FilterExpressionTextParserConcurrencyTests {
@Test
void parserInstancesShouldNotShareMutableErrorListener() throws Exception {
var firstParser = new FilterExpressionTextParser();
var secondParser = new FilterExpressionTextParser();
Field listenerField =
FilterExpressionTextParser.class.getDeclaredField("errorListener");
listenerField.setAccessible(true);
Object firstListener = listenerField.get(firstParser);
Object secondListener = listenerField.get(secondParser);
assertThat(firstListener).isNotSameAs(secondListener);
}
}
Actual result:
Expecting actual:
org.springframework.ai.vectorstore.filter.FilterExpressionTextParser$DescriptiveErrorListener@...
not to be the same as:
org.springframework.ai.vectorstore.filter.FilterExpressionTextParser$DescriptiveErrorListener@...
- Dominant language
- Java
- Stars
- 9.5k
- Forks
- 2.9k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 5
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from spring-projects/spring-ai
-
status: waiting-for-triage
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
spring-projects/spring-ai#7000 ·
-
status: waiting-for-triage
Difficulty 1/5 Under an hour Newbie friendliness 90/100
spring-projects/spring-ai#6998 ·
-
[Bug - MCP server] @McpTool error messages are emitted twice when the thrown exception has no cause Openstatus: waiting-for-triage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
spring-projects/spring-ai#6948 · 1 comment · 1 reaction ·
-
status: waiting-for-triage
Difficulty 1/5 Under an hour Newbie friendliness 90/100
spring-projects/spring-ai#6940 · 1 comment ·
-
status: waiting-for-triage
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
spring-projects/spring-ai#6928 · 1 comment ·
All issues in spring-projects/spring-ai
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
bug needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 1/5 Under an hour Newbie friendliness 94/100
objectionary/hone-maven-plugin#1061 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
spring-projects/spring-modulith#1895 ·