The "give me everything" value that IndexSearcher.search accepts makes GroupingSearch throw. One document is enough:
GroupingSearchgroups the hits of a query by a field value.search(searcher, query, groupOffset, groupLimit)returns one page of groups;setGroupDocsLimit(n)sets how many documents each group returns (default 1).- Top-N collectors allocate their arrays for N up front.
IndexSearcher.search(query, n)therefore caps n atmaxDocfirst, soInteger.MAX_VALUE("all") is safe there; that cap fixed the sameNegativeArraySizeExceptionin 2009 (LUCENE-2119).
a. With limit maxDoc = 1, GroupingSearch returns the group; with Integer.MAX_VALUE, 2147483647 + 1 wraps to -2147483648 and the search throws. IndexSearcher.search caps the count at maxDoc first; the same cap in GroupingSearch returns the group. Select the still to open it at full size. Generated with AI, checked against the code.- You index 1 document whose group field
gisa.IndexSearcher.search(q, Integer.MAX_VALUE)returns its 1 hit, andnew GroupingSearch("g").search(searcher, q, 0, 1)returns 1 group. - To get every group you pass
Integer.MAX_VALUEas the limit:search(searcher, q, 0, Integer.MAX_VALUE). You expect the same 1 group; the javadoc calls the limit "the number of groups to return", with no upper bound. - You get
NegativeArraySizeException: -2147483648, with assertions on or off. The next page (offset 1) throwstopNGroups must be >= 1 (got -2147483648), a number you never passed;setGroupDocsLimit(Integer.MAX_VALUE)fails too. - Why:
GroupingSearchhands the limit on unchanged, and the collector sizes an array by limit + 1 inint: 2147483647 + 1 wraps to -2147483648.IndexSearchercaps the count atmaxDoc(here 1) before sizing anything;GroupingSearchnever does. - Below the wrap, the same missing cap costs memory: one search with
groupDocsLimit= 10,000,000 allocated about 600 MB on a 20-document index.
Applications that group with GroupingSearch (the opt-in grouping module) and pass Integer.MAX_VALUE for all groups or all documents per group, or forward an uncapped page size. Every grouping mode; a 1-document index is enough. The search fails loudly; no wrong result observed. Workaround: for a valid offset and limit, cap both at maxDoc before the call, with the fix's rule.
Mechanism, terms and numbers591 words
GroupingSearch, the grouping module's convenience class, throws when the caller passes Integer.MAX_VALUE ("all") as groupLimit or as groupDocsLimit, although the same search with the limit set to reader.maxDoc() works and IndexSearcher.search(query, Integer.MAX_VALUE) works. With offset 0 the search throws NegativeArraySizeException: -2147483648, OutOfMemoryError: Requested array size exceeds VM limit or a queue-size IllegalArgumentException; with offset 1 it throws IllegalArgumentExceptions that name a value the caller never passed: "topNGroups must be >= 1 (got -2147483648)", "numHits must be > 0" or "maxDocsPerGroup must be >= 1 (got -2147483648)". Every grouping mode fails (term, function, term with caching enabled, the Supplier constructor, doc block), with assertions on and off; a large finite limit such as 10,000,000 does not throw but allocates memory in proportion to the limit. The cause is one missing cap: GroupingSearch hands the caller's offsets and limits unchanged to collector managers that add offset + limit in int and pre-size their queues and comparators by the limit, while IndexSearcher caps the count at maxDoc since LUCENE-2119 (2009). No silently wrong result was observed in 21,040 differential searches. Every release tested since 4.0.0 (2012) fails, as does main; capping the limits at maxDoc in GroupingSearch fixes it, and the grouping module's tests pass with that change.
GroupingSearch.search(searcher, query, groupOffset, groupLimit) GroupingSearch.java:128-138 values passed on unchanged
term / function / cached: groupByFieldOrFunction :141
new FirstPassGroupingCollectorManager(.., groupOffset, groupLimit, ..) :146-148
FirstPassGroupingCollectorManager.java:92-97 checks only offset >= 0, topNGroups >= 1
FirstPassGroupingCollectorManager.java:110 groupOffset + topNGroups <- int: 1 + MAX_VALUE = -2^31
FirstPassGroupingCollector.java:97-98 "topNGroups must be >= 1 (got " + topNGroups + ")"
FirstPassGroupingCollector.java:116 getComparator(topNGroups + 1) <- MAX_VALUE + 1 = -2^31
-> new float[-2147483648]: NegativeArraySizeException
new TopGroupsCollectorManager(.., groupDocsOffset, groupDocsLimit, ..) :197-205
TopGroupsCollectorManager.java:107 withinGroupOffset + maxDocsPerGroup <- int sum
TopGroupsCollector.java:127-147 per-group top-N collectors sized by it
doc block: groupByDocBlock :221
new BlockGroupingCollectorManager(.., groupDocsOffset + groupDocsLimit) :226-235 <- int sum at :235
BlockGroupingCollectorManager.java:143 groupOffset + topNGroups <- int sum
BlockGroupingCollector.java:217, :237 queue and comparators sized by topNGroups
IndexSearcher.searchAfter (core): :588 limit = Math.max(1, reader.maxDoc()); :597 cappedNumHits = Math.min(numHits, limit)- There are at most
maxDocgroups and at mostmaxDocdocuments per group, so a limit abovemaxDocnever changes the result; it only sizes the collectors.GroupingSearchsizes them for the caller and has no cap. - Every failing value passes the API's own checks (offset >= 0, limit >= 1).
| grouping | argument | offset 0 | offset 1 |
|---|---|---|---|
| term | groupLimit = MAX_VALUE | NegativeArraySizeException: -2147483648 | topNGroups must be >= 1 (got -2147483648) |
| term | groupDocsLimit = MAX_VALUE | OutOfMemoryError: Requested array size exceeds VM limit (field sort; relevance: initialCapacity must be > 0 and < 2147483630) | numHits must be > 0 |
| doc block | groupLimit = MAX_VALUE | maxSize must be >= 0 and < 2147483631; got: 2147483647 | topNGroups must be >= 1 (got -2147483648) |
| doc block | groupDocsLimit = MAX_VALUE | OutOfMemoryError: Requested array size exceeds VM limit | maxDocsPerGroup must be >= 1 (got -2147483648) |
Function grouping, term grouping with caching enabled (setCaching; it fails in the first pass, before any cached replay) and the Supplier<GroupSelector> constructor fail the same way (with groupLimit = MAX_VALUE, assertions on and off). Below the wrap, memory grows with the limit: on a 20-document index (5 groups of 4, field sort), one term-grouping search allocated 600,119,480 bytes with groupDocsLimit = 10,000,000 and 187,228,760 bytes with groupLimit = 10,000,000, against 56,488 bytes for IndexSearcher.search(q, 10,000,000, sort); with the cap, 120,680 and 120,264 bytes at every limit.
Exposure and likelihood316 words
- Who is exposed. Applications that use
GroupingSearchand passInteger.MAX_VALUEasgroupLimitorgroupDocsLimitto mean "all", or forward an uncapped user-chosen page size or offset. Term, function, cached and doc-block grouping all fail; the defaultgroupDocsLimitis 1, so the per-group path needs an explicitsetGroupDocsLimit. - What happens. That search throws an unchecked exception instead of returning the groups; with offset 1 or more the message names a value the caller never passed. No silent wrong result was observed in 21,040 differential searches, and the index does not change.
- Scale. None for
Integer.MAX_VALUE: a 1-document index is enough. Large finite limits cost memory in proportion to the limit (about 600 MB forgroupDocsLimit= 10,000,000 on a 20-document index). - Versions. Every release tested from 4.0.0 (2012) to 10.6.0 fails, and main; releases not run are inferred affected (the same
intsums in every tag read, no capping commit). - How likely. Rare: it fails on the first call, so developers who try this value switch to a finite value; Lucene's own
DatasetSplitterpassessetGroupDocsLimit(originalIndex.maxDoc()), and no public report was found. - Workaround. For a valid offset and limit (offset >= 0, limit >= 1), cap both before the call, with the rule of the fix:
maxDoc = Math.max(1, reader.maxDoc()),offset = Math.min(offset, maxDoc),limit = Math.max(1, Math.min(limit, maxDoc - offset)), for the group page and forsetGroupDocsOffset/setGroupDocsLimit. Leave other values as they are (or validate them first), as the fix does; applied to limit 0 or a negative limit, the formula would turn it into 1 instead of letting the API reject it. Capping only the limit (Math.min(limit, reader.maxDoc())) is not enough: a large offset still wrapsoffset + limit(e.g. offsetInteger.MAX_VALUE - 1with limit 20), and an empty index gives limit 0, which the API rejects ("topNGroups must be >= 1 (got 0)").
One JUnit test for the grouping module, public API only, no randomness: a 1-document index, default GroupingSearch settings, search(searcher, MatchAllDocsQuery, 0, Integer.MAX_VALUE), which must return the index's 1 group.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.search.grouping;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.SortedDocValuesField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.store.ByteBuffersDirectory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.lucene.util.BytesRef;
public class TestGroupingSearchLimitMaxValue extends LuceneTestCase {
public void testGroupLimitMaxValue() throws Exception {
try (Directory dir = new ByteBuffersDirectory()) {
try (IndexWriter w = new IndexWriter(dir, new IndexWriterConfig())) {
Document doc = new Document();
doc.add(new SortedDocValuesField("g", new BytesRef("a")));
w.addDocument(doc);
}
try (DirectoryReader reader = DirectoryReader.open(dir)) {
IndexSearcher searcher = new IndexSearcher(reader);
TopGroups<BytesRef> groups;
try {
GroupingSearch gs = new GroupingSearch("g");
groups = gs.search(searcher, new MatchAllDocsQuery(), 0, Integer.MAX_VALUE);
} catch (NegativeArraySizeException e) {
// expected: the 1 group that groupLimit = maxDoc returns; actual: limit + 1 wraps
throw new AssertionError("expected the 1 group of the index, got " + e, e);
}
assertEquals(1, groups.groups.length);
}
}
}
}
./gradlew :lucene:grouping:test --tests "org.apache.lucene.search.grouping.TestGroupingSearchLimitMaxValue" -Ptests.seed=DEADBEEF -Ptests.asserts=true
# assertions off: -Ptests.asserts=false (same failure)
- Expected
search(searcher, MatchAllDocsQuery, 0, Integer.MAX_VALUE)returns the index's 1 group, as the same search with limitmaxDocdoes.- Observed
NegativeArraySizeException: -2147483648fromFirstPassGroupingCollector.<init>(FirstPassGroupingCollector.java:116), assertions on and off.
More files, environment, full output196 words
Copy the file into lucene/grouping/src/test/org/apache/lucene/search/grouping/ and run the command. The test body is deterministic (ByteBuffersDirectory, a plain IndexWriterConfig), though it runs under Lucene's randomized test framework; pass -Ptests.asserts explicitly, because by default the build picks it from the seed. With the file added, :lucene:grouping:check -x test passes.
The exception is wrapped in an AssertionError that states expected and actual. The other symptoms (offset 1, groupDocsLimit, doc-block grouping) come from the same missing cap. The test is the suggested regression test as it stands.
| lucene | main 645d4fe14a20 (gradle); also fails on 10.6.0 and on the 4.0.0 to 10.5.2 releases tested |
|---|---|
| jdk | OpenJDK 25.0.3 |
| os | Linux aarch64 |
./gradlew :lucene:grouping:test --tests "org.apache.lucene.search.grouping.TestGroupingSearchLimitMaxValue" -Ptests.seed=DEADBEEF -Ptests.asserts=true
# gradle, main 645d4fe14a20, seed DEADBEEF, -Ptests.asserts=true (the same with false)
TestGroupingSearchLimitMaxValue > testGroupLimitMaxValue FAILED
java.lang.AssertionError: expected the 1 group of the index, got java.lang.NegativeArraySizeException: -2147483648
at __randomizedtesting.SeedInfo.seed([DEADBEEF:9E3B10358EB89447]:0)
at org.apache.lucene.search.grouping.TestGroupingSearchLimitMaxValue.testGroupLimitMaxValue(TestGroupingSearchLimitMaxValue.java:48)
Caused by:
java.lang.NegativeArraySizeException: -2147483648
at org.apache.lucene.core@11.0.0-SNAPSHOT/org.apache.lucene.search.FieldComparator$RelevanceComparator.<init>(FieldComparator.java:149)
at org.apache.lucene.core@11.0.0-SNAPSHOT/org.apache.lucene.search.SortField.getComparator(SortField.java:485)
at org.apache.lucene.search.grouping.FirstPassGroupingCollector.<init>(FirstPassGroupingCollector.java:116)
at org.apache.lucene.search.grouping.FirstPassGroupingCollectorManager.newCollector(FirstPassGroupingCollectorManager.java:108)
at org.apache.lucene.search.grouping.FirstPassGroupingCollectorManager.newCollector(FirstPassGroupingCollectorManager.java:52)
at org.apache.lucene.core@11.0.0-SNAPSHOT/org.apache.lucene.search.MultiCollectorManager.newCollector(MultiCollectorManager.java:53)
at org.apache.lucene.core@11.0.0-SNAPSHOT/org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:752)
at org.apache.lucene.search.grouping.GroupingSearch.groupByFieldOrFunction(GroupingSearch.java:175)
at org.apache.lucene.search.grouping.GroupingSearch.search(GroupingSearch.java:131)
at org.apache.lucene.search.grouping.TestGroupingSearchLimitMaxValue.testGroupLimitMaxValue(TestGroupingSearchLimitMaxValue.java:45)
:lucene:grouping:test (FAILURE): 1 test, 1 failure
# with the recommended fix, assertions on and off:
:lucene:grouping:test (SUCCESS): 1 test
BUILD SUCCESSFUL- The javadoc calls
groupLimit"The number of groups to return from the specified group offset", with no bound, and every failing value passes the API's own checks. - "topNGroups must be >= 1 (got -2147483648)" blames the caller for a number Lucene computed by overflowing
int. - Core fixed the same symptom as a bug: LUCENE-2119 caps
IndexSearcher.searchatmaxDoc.
The full argument208 words
- No documented bound.
groupLimit: "The number of groups to return from the specified group offset" (GroupingSearch.java:123);groupDocsLimit: "The number of documents to return inside a group" (:321). No javadoc, package doc, CHANGES or MIGRATE entry limits them, and every failing value passes the API's own checks (FirstPassGroupingCollectorManager.java:92-97,BlockGroupingCollectorManager.java:112-128). - The wrapped values have no rationale. "topNGroups must be >= 1 (got -2147483648)" and "maxDocsPerGroup must be >= 1 (got -2147483648)" report sums that Lucene computed (
FirstPassGroupingCollectorManager.java:110,BlockGroupingCollectorManager.java:143,GroupingSearch.java:235). - Core precedent.
lucene/CHANGES.txt, Bug fixes of 2.9.3 / 3.0.2: "LUCENE-2119: Don't throw NegativeArraySizeException if you pass Integer.MAX_VALUE as nDocs to IndexSearcher search methods." The fix is the cap atIndexSearcher.java:588/:597;FacetsCollectorManagerandDrillSidewayscap the same way. Integer.MAX_VALUEper group was made to work elsewhere. In LUCENE-4832 (#5897, 4.3.0), Michael McCandless asked in review "Could we just fix it so passing in Integer.MAX_VALUE for maxDocsPerGroup works?" for the join module'sToParentBlockJoinCollector, and the committed fix capped it with the group size.- The module's grouped-facet test (the grouped-facet API, not
GroupingSearch) passesInteger.MAX_VALUEas a limit and guards theoffset + limitsum itself (TestTermGroupFacetCollectorManager.java:106-118); no upstream test asserts the exception.
The devil's-advocate check161 words
The strongest case for "intended": the LUCENE-2119 issue text (#3195) calls Integer.MAX_VALUE "a nonsense value to pass in, since our PQ impl allocates the array up front"; core documents that TopScoreDocCollectorManager instances "pre-allocate a full array of length numHits"; no Lucene doc says that Integer.MAX_VALUE means "all" for these limits, and no index can hold that many documents (IndexWriter.MAX_DOCS is smaller); GroupingSearch is @lucene.experimental; the defaults are safe; Solr caps in its own layer; and the doc-block offset-0 case already gives an honest queue-size message.
Why it fails: LUCENE-2119 itself was resolved as a bug by capping in the convenience layer, and GroupingSearch is the convenience layer for grouping, which sizes the collectors on the caller's behalf; the pre-allocation note is on the core collector managers, not on GroupingSearch's limits; and no design reading explains an exception that names -2147483648. The defence fits the memory cost of large finite limits best, so present that part as secondary.
Recommended A. Cap the offsets and limits at maxDoc in GroupingSearch (validated)
Cap the offsets and limits at maxDoc inside GroupingSearch, as IndexSearcher.search does: offset' = min(offset, maxDoc), limit' = max(1, min(limit, maxDoc - offset')), for groups and for documents per group. Validated: the repro passes with assertions on and off, all 57 grouping-module tests pass, and all 21,040 differential searches match an exact reference.
All options and trade-offs3 options · 930 words
Option A fixes every GroupingSearch caller. Code that builds the collector managers directly still gets the wrapped sums; option B covers it and can be added to A. No CHANGES entry is drafted.
In GroupingSearch.search, cap groupOffset and groupLimit; for the documents per group, pass capped groupDocsOffset and groupDocsLimit to TopGroupsCollectorManager and BlockGroupingCollectorManager. Invalid values (negative offset, limit < 1) pass through unchanged, so they behave exactly as today: the group-page checks reject them, and invalid per-group values give the same result with and without the patch. +29/-4 lines in GroupingSearch.java. The code below is the complete patch; git apply takes it on 645d4fe14a20.
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
index 88b21b50686..2edabe58ce7 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
@@ -127,6 +127,15 @@ public class GroupingSearch {
@SuppressWarnings("unchecked")
public <T> TopGroups<T> search(
IndexSearcher searcher, Query query, int groupOffset, int groupLimit) throws IOException {
+ // A page of groups cannot extend past maxDoc (there are at most maxDoc groups): cap the
+ // caller's values, as IndexSearcher#search caps numHits, so that "offset + limit" cannot
+ // overflow and the collectors are not sized beyond the index. Invalid values are passed
+ // through unchanged so that the collectors still reject them.
+ final int maxDoc = Math.max(1, searcher.getIndexReader().maxDoc());
+ if (groupOffset >= 0 && groupLimit >= 1) {
+ groupOffset = Math.min(groupOffset, maxDoc);
+ groupLimit = Math.max(1, Math.min(groupLimit, maxDoc - groupOffset));
+ }
if (grouperFactory != null) {
return groupByFieldOrFunction(searcher, query, groupOffset, groupLimit);
} else if (groupEndDocs != null) {
@@ -137,6 +146,22 @@ public class GroupingSearch {
}
}
+ /** groupDocsOffset capped at maxDoc (same rule as the group page in #search). */
+ private int cappedDocsOffset(IndexSearcher searcher) {
+ final int maxDoc = Math.max(1, searcher.getIndexReader().maxDoc());
+ return groupDocsOffset >= 0 && groupDocsLimit >= 1
+ ? Math.min(groupDocsOffset, maxDoc)
+ : groupDocsOffset;
+ }
+
+ /** groupDocsLimit capped so that the capped offset plus the limit is at most maxDoc + 1. */
+ private int cappedDocsLimit(IndexSearcher searcher) {
+ final int maxDoc = Math.max(1, searcher.getIndexReader().maxDoc());
+ return groupDocsOffset >= 0 && groupDocsLimit >= 1
+ ? Math.max(1, Math.min(groupDocsLimit, maxDoc - cappedDocsOffset(searcher)))
+ : groupDocsLimit;
+ }
+
@SuppressWarnings({"unchecked", "rawtypes"})
protected <T> TopGroups<T> groupByFieldOrFunction(
IndexSearcher searcher, Query query, int groupOffset, int groupLimit) throws IOException {
@@ -200,8 +225,8 @@ public class GroupingSearch {
topSearchGroups,
groupSort,
sortWithinGroup,
- groupDocsOffset,
- groupDocsLimit,
+ cappedDocsOffset(searcher),
+ cappedDocsLimit(searcher),
includeMaxScore);
TopGroups<T> secondResult;
@@ -231,8 +256,8 @@ public class GroupingSearch {
groupSort.needsScores() || sortWithinGroup.needsScores(),
groupEndDocs,
sortWithinGroup,
- groupDocsOffset,
- groupDocsOffset + groupDocsLimit);
+ cappedDocsOffset(searcher),
+ cappedDocsOffset(searcher) + cappedDocsLimit(searcher));
return searcher.search(query, bcm);
}Trade-offs
A few cheap maxDoc() reads per search (the patch reads it up to 4 times for term and function grouping and 5 times for doc block, because the helpers recompute it and cappedDocsLimit calls cappedDocsOffset); no result changed in the differential. Direct users of FirstPassGroupingCollectorManager, TopGroupsCollectorManager and BlockGroupingCollectorManager are not covered (option B). Computing the capped values once is a possible clean-up.
What the checks validated
- Gradle in a scratch worktree of main
645d4fe14a20, seed DEADBEEF, assertions on and off: the repro alone fails stock and passes with the fix. - The repro with
TestGroupingSearch, the upstream test class ofGroupingSearch: stock 1 failure (the repro), with the fix 4 of 4 pass, each way. - All of
:lucene:grouping:testwith the fix, assertions on: 15 classes (14 upstream), 57 tests, 0 failures. :lucene:grouping:check -x test(google-java-format, ecjLint, forbiddenApis) passes with the fix and the repro added; the hunt's diff needed its 4-line comment re-wrapped (three of its lines were 101 columns).- Re-run in a second fresh scratch worktree of
645d4fe14a20(2026-10-30): stock, the repro fails with assertions on and off; with the fix, the repro andTestGroupingSearchpass 4 of 4 each way and all 57 tests of:lucene:grouping:testpass. It did not repeatcheck -x test. - The fact check's own fresh scratch worktree of
645d4fe14a20(2026-10-30), with the patch extracted from this doc and applied withgit apply: stock, the repro command fails with assertions on and off; with the patch, it passes both ways, the repro andTestGroupingSearchpass 4 of 4 each way, all 57 tests of:lucene:grouping:testpass and:lucene:grouping:check -x testpasses. - Earlier, in the repro harness: the finder's 8-case JUnit passes 8 of 8, 29 upstream grouping tests pass, a 21,040-search differential agrees 21,040 of 21,040, and a z3 bit-vector model proves, for the
intarithmetic and an abstract model of the group window (not the collectors' code), that the capped window selects the same groups and no sum can wrap for anymaxDocup toIndexWriter.MAX_DOCS; the allocation no longer grows with the limit.
Make the offset + limit sums in FirstPassGroupingCollectorManager.newCollector, TopGroupsCollectorManager.newCollector, BlockGroupingCollectorManager.newCollector and GroupingSearch.groupByDocBlock overflow-safe: reject offset > Integer.MAX_VALUE - limit in the constructors with a clear message, or saturate the sum.
Trade-offs
Removes the misleading -2147483648 messages for every caller, but on its own does not make "all" work: the first-pass collector still computes topNGroups + 1, and the queues are still pre-sized by the limit. Best as a complement to A.
State in the javadoc of search and setGroupDocsLimit that the limits pre-allocate and must not exceed maxDoc, and reject larger values with a clear message.
Trade-offs
Honest, but callers still need their own cap, and it differs from IndexSearcher.search, which accepts Integer.MAX_VALUE.
A service that forwards a user-chosen group page size or offset to GroupingSearch without capping it fails that request (or allocates in proportion to the size); Solr caps these sums in its own grouping layer.
Code reading left the grouping module's int offset + limit sums as a lead, and a probe on main showed the -2147483648 exceptions. A public-API JUnit, a differential check of 21,040 grouped searches against an exact reference (0 silent mismatches) and a z3 model of the eight int size sites followed.
The method in full194 words
- First signal (non-formal). Code reading of the
PriorityQueue/TopDocs.mergearea (2026-10-26) noted the grouping module'sintoffset + limitsums as a lead without running them; a planning probe on 2026-10-28 ran them on main, 10.5.2 andbranch_10_6and showedNegativeArraySizeException: -2147483648and "topNGroups must be >= 1 (got -2147483648)". - Then (semi-formal). A public-API JUnit (term and doc-block grouping x
groupLimitorgroupDocsLimit=Integer.MAX_VALUEx offset 0 or 1, each compared with the same search at limitmaxDoc): 8 of 8 fail. A bounded-exhaustive differential harness against an exact long-arithmetic reference: 6 seeded indexes of 2-15 documents in 1-3 segments, 5 grouping modes, field and relevance sorts, sequential and executor searchers, a boundary grid of offsets and limits: 21,040 searches, 7,872 agree, 13,168 throw, 0 silent mismatches; 21,040 of 21,040 agree with the cap. A z3 bit-vector model of the 8intsize sites: a wrap witness at every site, the wrap region is exactlyoffset + limit >= 2^31, and, in an abstract model of the group window, the cap is proved result-preserving and overflow-free; two fix mutants refuted. - The repro was later minimized to the one test above.
No prior report found (searched 2026-10-28 and rechecked 2026-10-30: GitHub issues and PRs, the JIRA archive, four mailing lists, downstream repositories, the web and the changed files of 195 open PRs). Closest: the same class fixed elsewhere, LUCENE-2119 (core) and LUCENE-4832 (join).
Searches6 searches
Read and not this bug: #3195 (LUCENE-2119, core IndexSearcher, 2009, fixed by capping at maxDoc); #5897 (LUCENE-4832, join module, made Integer.MAX_VALUE per group work); SOLR-4164 (Solr's own grouping layer, group.limit = -1); #10342 (LUCENE-9302, a different overflow in TopGroups.merge hit counts); #12942 (an honest "topNGroups must be >= 1 (got 0)"); #15574, #15603, #15936, #15995 and #16247, which introduced the collector managers and moved or added the sums (#15995 added the within-group offset and with it the TopGroupsCollectorManager sum, with no overflow discussion; one #15936 review discusses whether the offset belongs in the sum, not overflow). Open PRs #14996, #15210, #15494, #16548 and #16569 and the draft #16847 (long global doc ids: docBase as long, group heads per leaf, the IndexSearcher cap kept as a long) touch the grouping sources without changing the sums or capping a limit. Gaps: GitHub search does not fully cover PR review comments; some StackExchange queries were rate-limited; private reports cannot be searched.
| Where | When | How | Found |
|---|---|---|---|
| scripted prior-report search (two runs) | 2026-10-28 | 66 queries (GitHub 26, commits 3, downstream 2, the dev@, java-user@, issues@ and commits@ lists 24, JIRA 5, web 6; 540 distinct hits, 0 high) and the finder's 51-query run (0 high, 0 medium) | no report |
| GitHub, JIRA and the lists (manual) | 2026-10-28 | 24 searches over apache/lucene, apache/solr, Elasticsearch, OpenSearch and Lucene.NET (GroupingSearch, groupLimit, topNGroups, maxDocsPerGroup, the three messages, grouping with Integer.MAX_VALUE); 17 JQL queries (6 LUCENE, 11 SOLR, as listed in the prior-report record); every java-user@ thread about GroupingSearch and setGroupDocsLimit; the changed files of 195 open PRs | only precedents at other fix sites (LUCENE-2119, LUCENE-4832, SOLR-4164) |
| GitHub recheck | 2026-10-30 | GroupingSearch and topNGroups updated since 2026-10-28, groupDocsLimit, grouping Integer.MAX_VALUE; the 17 PRs created since 2026-10-28; the newest lucene/grouping commits | no report; no new grouping commit or PR |
| GitHub recheck (round 2) | 2026-10-30 | GroupingSearch updated today, topNGroups, groupDocsLimit, "-2147483648" grouping, grouping updated today; the PRs and issues created since the first recheck (#16953-#16955); the open #16952, which edits IndexSearcher bulk-scoring bounds only; the newest lucene/grouping and IndexSearcher.java commits | no report; no new grouping commit; the IndexSearcher cap is unchanged |
| GitHub recheck (round 3) | 2026-10-30 | GroupingSearch, topNGroups and grouping updated today, groupDocsLimit; items created or updated since a recent cutoff (#16952, #16790); "Integer.MAX_VALUE" grouping (7 items, incl. the draft #16847, whose 438 changed files were listed in full); the newest lucene/grouping and IndexSearcher.java commits | no report; #16847 touches grouping files but not the sums or the limits; no new grouping commit |
| GitHub recheck (round 4) | 2026-10-30 | the round-3 queries again; items updated since a recent cutoff now also include #16937 (the tracking issue for the AI-assisted bug list; its body and comments do not mention this bug) and #16900 (the openIfChanged issue, unrelated); the newest lucene/grouping and IndexSearcher.java commits; 645d4fe14a20...main | no report; no upstream fix (no lucene/grouping or IndexSearcher.java change on main since 645d4fe14a20) |
Born with the class: LUCENE-3778 (2012) added GroupingSearch with the uncapped int sums; first release 4.0.0. The 2026 collector managers moved the sums without changing them. Executed on 12 releases from 4.0.0-ALPHA to 10.5.2, 10.6.0 and main: all fail.
Versions tested10 rows
Introduced by 89b55566d83 "LUCENE-3778: Added a grouping utility class that makes it easier to use result grouping for pure Lucene apps." (2012-03-22, by martijnvg; migrated issue #4851; Subversion era, no PR, trunk only). The new GroupingSearch computed int topN = groupOffset + groupLimit and int topNInsideGroup = groupDocsOffset + groupDocsLimit and passed the caller's limits on with no cap. Core's IndexSearcher had capped at maxDoc since LUCENE-2119 (ae72952fa41, 2009).
Later moves, bug kept: in 2026 gaobinlong's collector managers took over the sums. FirstPassGroupingCollectorManager (#15574, 636e8e9f587) and BlockGroupingCollectorManager (#15936, d27d080d101) add groupOffset + topNGroups. TopGroupsCollectorManager was introduced by #15603 (e26a959e2c7) with maxDocsPerGroup passed on unchanged; its sum withinGroupOffset + maxDocsPerGroup came with #15995 (dc190df0955, 2026-05-04), which added the within-group offset. #16247 (3afffeef5a8) switched GroupingSearch's term path to the managers. The first-pass pre-sizing by topNGroups + 1 dates from LUCENE-1421 (9083cedb922, 2011), a caller-sized low-level collector that is not itself the bug.
First release. 4.0.0 (2012-10-11; the pre-release 4.0.0-ALPHA also fails). 3.x has no GroupingSearch. The offset-1 message "topNGroups must be >= 1 (got -2147483648)" is the same in every version; the offset-0 symptom varies with the collector internals. Point releases not run are inferred affected: the sums are in every tag read and no commit ever capped them.
| Version or commit | Verdict | Result |
|---|---|---|
main 645d4fe14a20 | affected | the one-test repro fails through gradle and the harness, assertions on and off; the finder's 8-case JUnit 8 of 8; a 9-case probe of every grouping mode 9 of 9, assertions on and off |
| 10.6.0 | affected | the one-test repro fails on the Maven Central jars, assertions on and off (the same commit as branch_10_6 4ae946e5a9b; listed apart because different tests ran) |
main a9779ef3c193 | affected | the finder's JUnit 8 of 8 (assertions on and off); an independent JUnit 8 of 10, both controls pass (assertions on and off) |
branch_10_6 4ae946e5a9b | affected | the finder's JUnit 8 of 8 (assertions off) (the commit of the 10.6.0 release tag) |
| 10.5.2, 10.0.0 | affected | the finder's JUnit 8 of 8; version probe 4 of 4 |
| 9.12.3, 9.0.0, 8.11.4, 7.7.3, 6.6.6, 5.5.5, 5.0.0 | affected | version probe: 4 of 4 term-grouping cases fail (9.12.3 also: independent JUnit 8 of 10) |
| 4.10.4, 4.0.0 | first | version probe: 8 of 8 term and doc-block cases fail; 4.0.0 is the first release with GroupingSearch |
| 4.0.0-ALPHA | affected | pre-release: 8 of 8 fail |
| 3.6.2, 3.5.0 | API absent | no GroupingSearch class |
the fix on main 645d4fe14a20 | not affected | the repro and TestGroupingSearch pass (assertions on and off), and all 57 tests of :lucene:grouping:test |
An independent reproducer, an intended-behaviour devil's advocate and an adjudication re-ran it and found it real; a reviewer from another model family could not run code and agreed on substance (a lens answered "not real" on procedural grounds only). This doc re-ran the one-test repro through gradle on 645d4fe14a20 and validated the fix.
Checks and verdicts629 words
The cross-model reviews were reading-only (they could not run code); every claim they read was executed by the other checks. The hunt's checks ran on main a9779ef3c193, whose grouping module equals 645d4fe14a20.
| Check | Verdict | What it found |
|---|---|---|
| Independent reproducer | real | Own 10-test JUnit outside the grouping package (an 8-document index of 4 blocks, a maxDoc-limit oracle with non-vacuity checks): 8 fail on main (assertions on and off), 10.5.2 and 9.12.3; both controls pass (IndexSearcher.search(q, Integer.MAX_VALUE) returns all hits; limits of 1000 give the maxDoc result). Its allocation probe confirms that memory grows with a large finite limit. |
| Cross-model review, refute lens | not real (high), procedural | An independent reviewer from another model family (OpenAI GPT-5.6), reading only: voted not real on procedure only, because it could not run Java; on substance it agreed with the root cause, judged the inputs in contract and rated the intended-behaviour defence weak. A separate re-run failed 8 of 8. |
| Cross-model review, intended lens | real (medium) | The same reviewer family, reading only: real, intended-behaviour defence weak. A separate run re-ran main with assertions on and 10.5.2 with assertions off: 8 of 8 fail. |
| Intended-behaviour devil's advocate | real | Built the strongest works-as-designed case (LUCENE-2119's "nonsense value", documented pre-allocation, @lucene.experimental, Solr's own cap) and rejected it; re-ran main (assertions on and off) and 10.5.2: 8 of 8 fail. |
| Adjudication | confirmed (high) | Re-ran the independent reproduction's JUnit on main with assertions on: 10 run, 8 failed, both controls pass. |
| History, prior art and security screen | since 4.0.0; new; not security-sensitive | 14 versions from 3.5.0 to 10.5.2 executed (3.5.0 and 3.6.2: API absent; 4.0.0-ALPHA onward: all fail); no prior report; no documented untrusted-input guarantee covers these limits. |
| Registration check, audit and repro minimization | reproduces; one test | Fresh seeds re-ran the finder's JUnit on main (8 of 8 fail, assertions on and off); the repro was reduced to one 1-document test on 645d4fe14a20, which fails with assertions on and off and passes with the fix shadowed. |
| Fix validation (this doc) | fix validated | Gradle in a scratch worktree of 645d4fe14a20: the repro fails stock and passes with option A, assertions on and off; with the fix TestGroupingSearch, all 57 tests of :lucene:grouping:test and :lucene:grouping:check -x test pass. The repro also fails on the 10.6.0 jars. A second fresh-worktree run later the same day reproduced the stock failure (assertions on and off) and the fixed passes (the repro with TestGroupingSearch each way, the 57-test module); it did not repeat check -x test or the 10.6.0 jars. |
| Fact checks of this doc (two rounds) | real; doc wording corrected | Round 1 (2026-10-30) re-ran the one-test repro through gradle on 645d4fe14a20 (fails, assertions on and off) and the fix (the repro, TestGroupingSearch, all 57 tests of :lucene:grouping:test and :lucene:grouping:check -x test pass), and ran a 9-case probe of every grouping mode (9 of 9 fail, assertions on and off). Round 2, in its own fresh worktree, re-ran the doc's exact command (fails with assertions on and off, the output line for line) and the patch as printed here (the repro, TestGroupingSearch, all 57 tests and check -x test pass), the harness on main and on the 10.6.0 jars (fails, assertions on and off; passes with the patch shadowed), a probe of 10 invalid per-group values (the same output with and without the patch) and every round-3 prior-art query (identical results). A reviewer from another model family (OpenAI GPT-5.6, reading only) checked both rounds and agreed on the mechanism. The wording they flagged (evidence paths, the workaround and its validity guard, maxDoc reads, credits, the recheck times, the scope of the second fix run, overclaims) is corrected; see an unpublished file. |
The diagram as a still image, generated with AI and checked against the code. It is under 10 MB, the limit for a GitHub attachment.
- PNG 526 KB
Finding record, Lucene and upstream sources, repro files and diagram notes1,634 words
- Registry title
- GroupingSearch with groupLimit or groupDocsLimit = Integer.MAX_VALUE ('all remaining groups/documents') throws NegativeArraySizeException, OutOfMemoryError or an IllegalArgumentException naming -2147483648, because it does not cap the limits at maxDoc as IndexSearcher.search does and its collectors add offset + limit in int (every release since 4.0.0)
- Area
- grouping / GroupingSearch (term, function, cached two-pass and doc-block grouping) x the first-pass, TopGroups and block collector managers
- Priority
- Low, rank 640: GroupingSearch fails loudly on the usual Integer.MAX_VALUE 'all' idiom in a module and never returns wrong groups, like its UnifiedHighlighter MAX_VALUE sibling LFV-438.
- Impact class
- wrong error
- Impact note
- Hits applications on every release from 4.0.0 to 10.6.0 and on main that pass a 'no limit' value such as Integer.MAX_VALUE as GroupingSearch's groupLimit (search) or groupDocsLimit (setGroupDocsLimit), with default settings in every grouping mode and with -ea or -da: the search throws instead of returning the groups, and with an offset of 1 or more the exception names a value the caller never passed (-2147483648); large finite limits allocate memory in proportion to the limit, not to the index (about 600 MB for groupDocsLimit = 10,000,000 on a 20-document index); the failure is loud on the first such search, no result is ever silently wrong, and capping the limit at reader.maxDoc() avoids it.
- Summary
- You call GroupingSearch.search(searcher, query, 0, Integer.MAX_VALUE) or setGroupDocsLimit(Integer.MAX_VALUE) to get every group, or every document of each group, and expect the same TopGroups as with a limit of maxDoc, the way IndexSearcher.search(query, Integer.MAX_VALUE) returns every hit. Instead the search throws: with offset 0 a NegativeArraySizeException -2147483648, an OutOfMemoryError 'Requested array size exceeds VM limit' or a queue-size IllegalArgumentException, and with offset 1 an IllegalArgumentException such as 'topNGroups must be >= 1 (got -2147483648)' or 'numHits must be > 0'. GroupingSearch hands the limits on uncapped to collectors that add offset + limit in int and pre-size their queues by the limit; nothing is ever returned wrong.
- Introduced
- 89b55566d8392657be86e1441a329373e9132257 (2012-03-22, 'LUCENE-3778: Added a grouping utility class that makes it easier to use result grouping for pure Lucene apps', by martijnvg; LUCENE-3778 is apache/lucene#4851; JIRA-patch era, no pull request; committed to trunk only, first shipped in 4.0.0): the new GroupingSearch computed 'int topN = groupOffset + groupLimit' and 'groupDocsOffset + groupDocsLimit' and passed the caller's limits on with no cap [read: git log -S on the full history; exec: 4.0.0-ALPHA fails 8 of 8 and 3.5.0/3.6.2 have no GroupingSearch]. The bug was born with the class and is not a regression. The sums later moved into FirstPassGroupingCollectorManager (636e8e9f587, #15574), TopGroupsCollectorManager (e26a959e2c7, #15603) and BlockGroupingCollectorManager (d27d080d101, #15936), and GroupingSearch's term path switched to the managers in 3afffeef5a8 (#16247), all by gaobinlong in 2026, with the same effect. The first-pass pre-sizing by topNGroups + 1 dates from LUCENE-1421 (9083cedb922, 2011), a caller-sized low-level collector that is not itself the bug. (2012-03-22 (author and commit date of 89b55566d83))
- First affected version
- 4.0.0 (released 2012-10-11) [exec; the pre-release 4.0.0-ALPHA also fails 8 of 8]; 3.6.x is not affected because it has no GroupingSearch (LUCENE-3778 went to trunk only; 3.5.0 and 3.6.2 executed: API absent; 3.6.0/3.6.1 jar listings)
- Affected versions
- [exec] 4.0.0-ALPHA, 4.0.0, 4.10.4, 5.0.0, 5.5.5, 6.6.6, 7.7.3, 8.11.4, 9.0.0, 9.12.3, 10.0.0 and 10.5.2 fail with the follow-up's version-specific history probes (8 of 8 cases in 4.x, 4 of 4 term-grouping cases from 5.0.0 on, -da), the finder's JUnit fails 8 of 8 on 10.0.0, 10.5.2, branch_10_6 head 4ae946e5a9b (10.6.0, released 2026-10-29) and main a9779ef3c193 (-ea and -da), the independent reproduction's own JUnit fails 8 of 10 (both controls pass) on main (-ea and -da), 10.5.2 and 9.12.3, and the registration check re-ran the finder's JUnit on main (-da, seed 5EED0387: 8 run, 8 failed). [read] every other point release from 4.0.0 to 10.5.2 is inferred affected: the int sums are present in every tag read and GroupingSearch's history has no capping change. The wrapped-sum message 'topNGroups must be >= 1 (got -2147483648)' for groupOffset 1 is identical in every version; the offset-0 symptoms vary with the collector internals (field-sorted groupDocsLimit = MAX_VALUE: OutOfMemoryError on 4.0.x and main, NegativeArraySizeException 4.10.4-6.6.6, PriorityQueue maxSize IllegalArgumentException 7.7.3-10.5.2). Not fixed upstream: upstream main 645d4fe14a20 (author date 2026-10-28) has no grouping commit after a9779ef3c193. All runs on Linux aarch64 with JDK 25.0.3.
- Status
- documented (brief, checks and a per-finding doc exist)
- Verification
- Confirmed by AI-run checks: an independent repro, a cross-model review that could only read the code (its “not real” is procedural), an intended-behaviour check, a prior-report search and a skeptical audit; not yet triaged by a person.
- Found by
- non-formal: code reading; also reached by Z3, exhaustive check
- Upstream and prior reports
- none found (the prior-report record, verdict new, searched 2026-10-28, read-only; finder's search 2026-10-28; refresh 2026-10-28): a 66-query scripted prior-report search (GitHub 26, commits 3, downstream 2, the dev@, java-user@, issues@ and commits@ lists 24, JIRA 5, web 6; 540 distinct hits, 0 high, 5 medium) and the finder's 51-query run (168 hits, 0 high, 0 medium); 24 manual GitHub searches over apache/lucene, apache/solr, elastic/elasticsearch, opensearch-project/OpenSearch and apache/lucenenet; LUCENE and SOLR JIRA queries; lists.apache.org searches; web searches; the changed files of every open apache/lucene PR updated since 2026-06-01 (195) and of the open grouping PRs. Nothing reports GroupingSearch or the grouping collector managers failing on huge or Integer.MAX_VALUE limits, or offset + limit wrapping in int. Precedents for the same class at other fix sites, not reports of this bug: #3195 (LUCENE-2119, core IndexSearcher, fixed in 2009 by capping n at maxDoc, before the grouping module existed), #5897 (LUCENE-4832, join ToParentBlockJoinCollector, 2013), SOLR-4164 (Solr's own grouping layer). The open PRs that touch the grouping sources (#14996, #15210, #15494, #16548, #16569) neither change the sums nor cap the limits; #10342 (LUCENE-9302, int total hit counts in TopGroups.merge) is another root cause. Refresh: no apache/lucene issue or PR updated since 2026-10-26 mentions GroupingSearch; 'topNGroups' finds only #15936, #12942 and #4851; 'groupDocsLimit' and '"got -2147483648"' find nothing; none of the 20 PRs created since 2026-10-26 (#16907-#16936) touches lucene/grouping (#16931 concerns MMapDirectory arena grouping, unrelated); the newest lucene/grouping commit on upstream main 645d4fe14a20 is 3e4a7a02ce0 (2026-10-07, #16779, unrelated).
- Lucene commit tested
- main
645d4fe14a20(2026-10-28) through gradle in a scratch worktree (removed afterwards), seed DEADBEEF, assertions on and off: stock, the one-test repro fails; with the recommended fix it passes, together withTestGroupingSearch, all of:lucene:grouping:test(57 tests, assertions on) and:lucene:grouping:check -x test. A second fresh scratch worktree (2026-10-30) reproduced the stock failure (assertions on and off) and the fixed passes (the repro withTestGroupingSearcheach way, the 57-test module); it did not repeatcheck -x test. The fact check's own fresh worktree repeated the stock failure, the fixed passes, the 57-test module andcheck -x test. Through the repro harness: the one-test repro on645d4fe14a20(assertions on and off, fix shadowed) and on the 10.6.0 jars from Maven Central (assertions on and off); a 1-document diagram probe and the finder's 8-case JUnit on645d4fe14a20; a 9-case probe of every grouping mode on645d4fe14a20(assertions on and off, the doc's fact check); on maina9779ef3c193the finder's JUnit, an independent 10-test JUnit and a devil's-advocate re-run (assertions on and off) and an adjudication re-run (assertions on); the finder's JUnit onbranch_10_64ae946e5a9b(assertions off) and on 10.0.0 and 10.5.2; the independent JUnit on 10.5.2 and 9.12.3; version probes on 12 releases from 4.0.0-ALPHA to 10.5.2; a 21,040-search differential harness and an allocation probe ona9779ef3c193. The grouping module andIndexSearcherare identical ata9779ef3c193and645d4fe14a20. OpenJDK 25.0.3, Linux aarch64 (the only platform run).
- Finding record
lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java:44 (at a9779ef3c193) (@lucene.experimental), :123 ('@param groupLimit The number of groups to return from the specified group offset', no bound), :128-138 (search passes groupOffset and groupLimit unchanged), :146-148 (FirstPassGroupingCollectorManager gets the raw groupOffset and groupLimit), :197-205 (TopGroupsCollectorManager gets the raw groupDocsOffset and groupDocsLimit), :226-235 (groupByDocBlock, int sum groupDocsOffset + groupDocsLimit at :235), :321 ('@param groupDocsLimit The number of documents to return inside a group', no bound)lucene/grouping/src/java/org/apache/lucene/search/grouping/FirstPassGroupingCollectorManager.java:92-97 (at a9779ef3c193) (validation accepts topNGroups = Integer.MAX_VALUE), :110 (int sum groupOffset + topNGroups); FirstPassGroupingCollector.java:97-98 ('topNGroups must be >= 1 (got ...)' reports the wrapped sum), :116 (getComparator(topNGroups + 1): NegativeArraySizeException at topNGroups = Integer.MAX_VALUE)lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroupsCollectorManager.java:107 (at a9779ef3c193) (int sum withinGroupOffset + maxDocsPerGroup); TopGroupsCollector.java:89-98 (per-group top-N collectors pre-sized by maxDocsPerGroup)lucene/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollectorManager.java:125-128 (at a9779ef3c193) ('maxDocsPerGroup must be >= 1 (got ...)' reports the wrapped sum), :143 (int sum groupOffset + topNGroups); BlockGroupingCollector.java:217 and :237 (queue and comparators pre-sized by topNGroups)lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java:588-599 (at a9779ef3c193) and :721-733 (core caps numHits: cappedNumHits = Math.min(numHits, Math.max(1, maxDoc)))lucene/grouping/src/test/org/apache/lucene/search/grouping/TestTermGroupFacetCollectorManager.java:106-118 (at a9779ef3c193) (the module's own test passes Integer.MAX_VALUE limits to its facet API and guards the offset + limit sum itself)Lucene main a9779ef3c193 SECURITY.md lines 28, 38, 42, 46, 50 (threat model; via follow-up the security record)
- The finding in 30 seconds
lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java:41-46 (convenience class, @lucene.experimental), :55 (groupDocsLimit = 1), :123, :128-138, :141-148, :197-205, :221-235, :321 @ 645d4fe14a20lucene/grouping/src/java/org/apache/lucene/search/grouping/FirstPassGroupingCollectorManager.java:92-97, :105-112; FirstPassGroupingCollector.java:97-98, :116; TopGroupsCollectorManager.java:100-108; TopGroupsCollector.java:122-148; BlockGroupingCollectorManager.java:112-128, :140-144; BlockGroupingCollector.java:210-240 @ 645d4fe14a20lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java:587-601, :719-733; FieldComparator.java:148-149 (RelevanceComparator: new float[numHits]) @ 645d4fe14a20
- Who is affected
lucene/classification/src/java/org/apache/lucene/classification/utils/DatasetSplitter.java:124 @ 645d4fe14a20lucene/grouping/src/java/org/apache/lucene/search/grouping/FirstPassGroupingCollectorManager.java:92-97 (the checks), :110 (groupOffset + topNGroups); GroupingSearch.java:313, :324 (setGroupDocsOffset, setGroupDocsLimit) @ 645d4fe14a20
- Why it looks unintended
lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java:41-46, :115-126, :318-327 @ 645d4fe14a20lucene/CHANGES.txt:18412, :18433, :18439-18441 (LUCENE-2119 under Bug fixes, 2.9.3 / 3.0.2), :13905, :13957, :14007-14008 (LUCENE-4832, 4.3.0) @ 645d4fe14a20lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollectorManager.java:45-46; lucene/facet/src/java/org/apache/lucene/facet/FacetsCollectorManager.java:257; DrillSideways.java:199, :231 @ 645d4fe14a20lucene/grouping/src/test/org/apache/lucene/search/grouping/TestTermGroupFacetCollectorManager.java:106-118 @ 645d4fe14a20
- TestGroupingSearchLimitMaxValue.java (one test):
repro/LFV-964/src/org/apache/lucene/search/grouping/TestGroupingSearchLimitMaxValue.java(54 lines)
It is made separately from this text; its numbers come from the executed diagram probe on main.
assets/LFV-964/bug.png(526 KB)
