A sloppy PhraseQuery in which two different terms each repeat (for example "a b a b"~1) misses documents of a segment, exact-phrase matches included, when the segment's first candidate document has two of those terms stacked at one position, because SloppyPhraseMatcher builds its repetition groups once, from that document, by position instead of by term

Finding LFV-187Area: search / phrase queries (SloppyPhraseMatcher repetition groups: gatherRptGroups, non-multi-term branch)Priority: lowImpact: silent wrong resultsNovelty: known upstream

AI-assisted finding, confirmed by automated checks, not yet triaged by a human Lucene committer. This site files nothing upstream.

What it shows

You index text into a field whose analysis can put two words at one position (for example an index-time synonym) and search with a sloppy phrase such as "a b a b"~1, in which two different words each repeat; you expect every document within the slop, and certainly every document that holds the exact phrase, to match, whatever other documents share its segment. SloppyPhraseMatcher works out which phrase positions repeat each other only once per segment, on the first candidate document, and groups them by equal position in that document rather than by term, so when that document has a and b stacked at one position both words land in one group and the matcher then asks for more occurrences than exist. That document and later documents of the segment are missed with no error: in the two-document repro the plain document 'a b a b' matches with slop 0 but not with slop 1, while the same document indexed alone matches with slop 1.

Expected vs actual

Files

Run it

# Lucene checkout at the tested commit, built with: ./gradlew --no-daemon assemble   (JDK 25)
LUCENE=/path/to/lucene; V=12.0.0-SNAPSHOT
CP=$LUCENE/lucene/core/build/libs/lucene-core-$V.jar
CP=$CP:$LUCENE/lucene/codecs/build/libs/lucene-codecs-$V.jar
CP=$CP:$LUCENE/lucene/test-framework/build/libs/lucene-test-framework-$V.jar
CP=$CP:randomizedtesting-runner-2.9.2.jar:junit-4.13.2.jar:hamcrest-3.0.jar   # test-framework dependencies (Maven Central)
CP=$CP:junit-platform-console-standalone-6.1.3.jar   # JUnit Platform console launcher (Maven Central)

javac -d classes -cp "$CP" $(find src -name '*.java')

# run 1: assertions on, seed DEADBEEF
java -ea -esa --add-modules jdk.incubator.vector --enable-native-access=ALL-UNNAMED -Dtests.seed=DEADBEEF \
     -cp "classes:$CP" org.junit.platform.console.ConsoleLauncher \
     execute --select-class org.apache.lucene.search.TestSloppyPhraseRepeatGroupsFirstDoc

Gradle alternative: copy the test into the matching module's src/test/ tree of the checkout and run ./gradlew -p lucene/<module> test --tests <class> -Ptests.seed=<seed> (add -Ptests.asserts=false for a run without assertions).

Feedback

Open an issue in lucene-ai-bug-hunt. Please do not open issues or pull requests in apache/lucene about this finding unless a Lucene committer agrees it should be filed.

Snapshot of 2026-11-04. AI-assisted; not yet triaged by a human Lucene committer. Feedback: open an issue in lucene-ai-bug-hunt.