All findings · Lucene finding · LFV-994 · ssdv-facet-child-queue-presized-by-topn

SortedSetDocValues facets size the child queue from topN, so getTopChildren(Integer.MAX_VALUE, dim) throws where taxonomy facets return every label

On SortedSetDocValues facets, asking for every label with getTopChildren(Integer.MAX_VALUE, dim) throws IllegalArgumentException, even on a dim with 3 labels, because the child priority queue is sized from topN instead of the label count. Taxonomy facets cap the same queue and return the 3 labels.

Summary

Priority
Low, rank 643SSDV getTopChildren and getAllDims fail loudly on the Integer.MAX_VALUE 'all children' idiom that taxonomy facets accept, a module bug that never returns wrong results, so it leads the new MAX_VALUE facet rows right after the GroupingSearch row LFV-964.
Impact
wrong error
Since
4.7.0 (the LUCENE-5339 facet API rewrite, 2013)introduced 2013-11-14 · over 12 years
Affected
4.7.0 to 10.6.0 and main (18 version points run, the releases in between by reading); 4.3.0 to 4.6.1 not affected
Status
documented
Found by
AI tools: a numeric-limits probe, then a differential harness

AI-assisted page: this finding was first signalled by code reading or testing and then checked with AI tools; the checks it went through, and what each found, are under Prior reports, history and checks. Not yet triaged by a human. Snapshot of 2026-11-06.

The finding in 30 seconds

The SortedSetDocValues counter sizes its top-children queue by the topN you pass, not by how many labels the dim can have, and Lucene's priority queue refuses 2,147,483,631 slots or more.

Background: two kinds of facets and topN

  1. Lucene counts facet labels in two main ways: taxonomy facets keep the labels in a side index; SortedSetDocValues (SSDV) facets keep them in a doc-values field of the main index. Both implement the same Facets API.
  2. getTopChildren(topN, dim) returns the topN labels of a dim with the highest counts. The counter picks them with a priority queue that holds at most topN entries. Some callers, Lucene's own taxonomy tests among them, pass Integer.MAX_VALUE to mean "all children".
  3. Lucene's PriorityQueue allocates its whole array, topN + 1 slots, when it is created, and refuses sizes of 2,147,483,631 or more (Lucene's maximum array length, ArrayUtil.MAX_ARRAY_LENGTH).
Summary of the bug: 3 documents with the SortedSetDocValues facet labels a, b and c in dim "dim". getTopChildren(Integer.MAX_VALUE, "dim") passes topN = 2,147,483,647 to new TopOrdAndIntQueue(topN) at AbstractSortedSetDocValueFacetCounts.java:325; PriorityQueue refuses any size of 2,147,483,631 or more and throws IllegalArgumentException "maxSize must be >= 0 and < 2147483631; got: 2147483647" instead of returning a (1), b (1), c (1). Taxonomy facets cap the same queue with Math.min(taxoReader.getSize(), topN) and return the 3 labels. Below the limit the SSDV queue still reserves topN + 1 slots: getTopChildren(1 << 24) allocates 67,111,104 bytes for 3 labels. The fix caps the queue with Math.min(topN, state.getSize()).
One dim with 3 labels: getTopChildren(Integer.MAX_VALUE) makes SortedSetDocValues facets ask for a queue of 2,147,483,647 slots, which PriorityQueue refuses; taxonomy facets cap the queue at the taxonomy's size and return the 3 labels. Select the still to open it at full size. Generated with AI, checked against the code.

The finding, step by step

  1. Index 3 documents with one SortedSetDocValues facet label each in dim dim: a, b, c (default FacetsConfig). Count all hits with SortedSetDocValuesFacetCounts.
  2. Ask for every label: getTopChildren(Integer.MAX_VALUE, "dim"). The only topN check rejects topN <= 0, and taxonomy facets answer this call with all labels, so you expect a (1), b (1), c (1), as getTopChildren(10, "dim") returns.
  3. You get IllegalArgumentException: maxSize must be >= 0 and < 2147483631; got: 2147483647, with assertions on and off. getAllDims(Integer.MAX_VALUE), getTopDims(10, Integer.MAX_VALUE) and the concurrent counts fail the same way.
  4. Why: to pick the top labels, the counter creates new TopOrdAndIntQueue(topN) (AbstractSortedSetDocValueFacetCounts.java:325) without capping topN at the 3 labels. Lucene's PriorityQueue allocates all topN + 1 slots up front and refuses 2,147,483,631 or more. Taxonomy facets build the same queue with Math.min(taxoReader.getSize(), topN).
  5. Below that limit the call works but still reserves the slots: getTopChildren(1 << 24, "dim") on the same 3 labels allocates 67,111,104 bytes, against 2,280 bytes at topN = 10 and 1,344 bytes on taxonomy facets. Close to the limit it can run out of heap instead.

Who is affected

Code using SortedSetDocValues facets, plain or concurrent, that passes Integer.MAX_VALUE (or any topN from 2,147,483,631) to getTopChildren, getAllDims or getTopDims to mean "all children": every such call on a dim with counts throws, at any index size, since 4.7.0. Large legal values reserve topN + 1 slots per dim.

Mechanism, terms and numbers571 words

SortedSetDocValues (SSDV) facets choose the top children of a dim with a priority queue that they size to the caller's topN, with no cap at the number of labels (AbstractSortedSetDocValueFacetCounts.java:325). Lucene's PriorityQueue allocates topN + 1 slots up front and refuses 2,147,483,631 or more. So getTopChildren(Integer.MAX_VALUE, dim), which Lucene's own taxonomy tests use to ask for every child, throws IllegalArgumentException on a dim with 3 labels as soon as one of its children has a count, and getAllDims(Integer.MAX_VALUE) and getTopDims(.., Integer.MAX_VALUE) fail the same way, in the plain and the concurrent counts. Facets.validateTopN accepts every topN > 0, and taxonomy facets cap the same queue with Math.min(taxoReader.getSize(), topN) and return every label. Below the limit the call returns the right labels but reserves the slots: 67,111,104 bytes for topN = 2^24 on 3 labels; close to the limit it can run out of heap instead. Default configuration, any index size, assertions on and off; 4.7.0 to 10.6.0 and main are affected (18 version points run, the releases in between by reading). Up to 4.6.1 the old API documented Integer.MAX_VALUE as "all children" and SSDV honoured it. The fix is one line: cap the queue at the field's label count, as taxonomy facets do.

The bug

  1. getTopChildren checks topN with validateTopN (AbstractSortedSetDocValueFacetCounts.java:57), which rejects only topN <= 0 (Facets.java:80-84), then calls getTopChildrenForPath (:61) and computeTopChildren (:300-301). getAllDims (:112-140) does the same for every dim; getTopDims passes topNChildren the same way (:189-191, :226).
  2. computeTopChildren (:309-339) walks the path's child ordinals and, at the first child with a count, creates the queue: q = new TopOrdAndIntQueue(topN); (:325). Nothing caps topN at the number of children or labels. With no counted child the queue is never built and the call returns normally.
  3. TopOrdAndIntQueue and TopOrdAndNumberQueue pass topN straight to PriorityQueue (TopOrdAndIntQueue.java:24, TopOrdAndNumberQueue.java:42). The PriorityQueue constructor throws IllegalArgumentException for maxSize >= ArrayUtil.MAX_ARRAY_LENGTH (PriorityQueue.java:121-124; Integer.MAX_VALUE - NUM_BYTES_ARRAY_HEADER, 2,147,483,631 here) and otherwise allocates new Object[maxSize + 1] (:129, :134). Its javadoc says it pre-allocates that array (:34); the class is @lucene.internal (:39).
  4. SortedSetDocValuesFacetCounts and ConcurrentSortedSetDocValuesFacetCounts both extend AbstractSortedSetDocValueFacetCounts, so both fail; DrillSideways (executed) and MultiFacets (by reading) hand them out for SSDV dims.
  5. Taxonomy facets build the same queue type as new TopOrdAndIntQueue(Math.min(taxoReader.getSize(), topN)) (TaxonomyFacets.java:250-251), and the other implementations cap too. The bound SSDV needs is at hand: SortedSetDocValuesReaderState.getSize(), "Number of unique labels", is 3 in the repro index.

The numbers (main, the repro's 3-document index)

callSSDV facetstaxonomy facets
getTopChildren(10, "dim")a (1), b (1), c (1); 2,280 bytes-
getTopChildren(1000, "dim")a (1), b (1), c (1); 6,240 bytes-
getTopChildren(1 << 24, "dim")a (1), b (1), c (1); 67,111,104 bytes1,344 bytes
getTopChildren(2147483631, "dim")IllegalArgumentException-
getTopChildren(Integer.MAX_VALUE, "dim")IllegalArgumentExceptiona (1), b (1), c (1)
getAllDims(Integer.MAX_VALUE)IllegalArgumentExceptionthe dim with its 3 labels
with the fix, getTopChildren at 10, 1000, 1 << 24 or Integer.MAX_VALUEa (1), b (1), c (1); 2,248 bytes-
with the fix, getTopChildren(2147483631, "dim")a (1), b (1), c (1)-
with the fix, getAllDims(Integer.MAX_VALUE)the dim with its 3 labels-

Allocation is the minimum over 5 calls after 3 warm-up calls (thread allocation counter). The planning probe on another index measured 381 MiB per dim at topN = 10^8.

Exposure and likelihood283 words
  • Who is hit. Callers of getTopChildren, getAllDims or getTopDims(.., topNChildren) on SortedSetDocValuesFacetCounts or ConcurrentSortedSetDocValuesFacetCounts (also through DrillSideways, executed, or MultiFacets, by reading, for SSDV dims) with Integer.MAX_VALUE, or any topN from 2,147,483,631 up. The call throws only when the dim or path has at least one child with a count; with none, the queue is never built (AbstractSortedSetDocValueFacetCounts.java:319-325). Code that moves from taxonomy to SSDV facets with that idiom, or shares it between both, meets it on the first such call.
  • Large but legal topN. Values such as 2^24 or 10^8 used as "all" work and return correct results, but reserve topN + 1 queue slots per dim with hits, per call: 67,111,104 bytes at 2^24 on 3 labels, 381 MiB per dim at 10^8. Values close to 2,147,483,631 can fail with OutOfMemoryError instead, depending on the heap: with a 1 GiB heap the hunt's harness got OutOfMemoryError: Java heap space at topN = 2,147,483,630.
  • Default vs opt-in. Default FacetsConfig, codec and IndexSearcher; no setting is needed. SSDV faceting is an opt-in API marked @lucene.experimental; the trigger is the topN value.
  • Who is not. The child queues of taxonomy facets and the other Facets implementations, which cap topN (taxonomy's getTopDims dimension queue is uncapped: the separate LFV-983). SSDV calls below 2,147,483,631 return the right labels as long as the heap holds topN + 1 slots.
  • Severity. Loud: an exception for that call; no wrong results, nothing written to the index.
  • How likely. Rare: no public SSDV caller with the Integer.MAX_VALUE idiom was found (downstream code uses it on taxonomy and range facets, which cap), and the searches found no public report since 4.7.0 (2014).

Minimal repro

One JUnit class, one method, 3 documents, default FacetsConfig; besides Lucene's test framework it uses only public API. It fails with assertions on and off and is also the suggested regression test.

TestSortedSetFacetsTopNMaxValue.java (JUnit for Lucene's build)62 lines
/*
 * 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.facet.sortedset;

import org.apache.lucene.document.Document;
import org.apache.lucene.facet.FacetResult;
import org.apache.lucene.facet.Facets;
import org.apache.lucene.facet.FacetsCollector;
import org.apache.lucene.facet.FacetsCollectorManager;
import org.apache.lucene.facet.FacetsConfig;
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.Directory;
import org.apache.lucene.tests.util.LuceneTestCase;

public class TestSortedSetFacetsTopNMaxValue extends LuceneTestCase {

  public void testGetTopChildrenWithMaxValueTopN() throws Exception {
    FacetsConfig config = new FacetsConfig();
    try (Directory dir = newDirectory()) {
      try (IndexWriter w = new IndexWriter(dir, new IndexWriterConfig())) {
        for (String label : new String[] {"a", "b", "c"}) {
          Document doc = new Document();
          doc.add(new SortedSetDocValuesFacetField("dim", label));
          w.addDocument(config.build(doc));
        }
      }
      try (DirectoryReader reader = DirectoryReader.open(dir)) {
        FacetsCollector fc =
            new IndexSearcher(reader).search(new MatchAllDocsQuery(), new FacetsCollectorManager());
        Facets facets =
            new SortedSetDocValuesFacetCounts(
                new DefaultSortedSetDocValuesReaderState(reader, config), fc);
        FacetResult result;
        try {
          result = facets.getTopChildren(Integer.MAX_VALUE, "dim");
        } catch (IllegalArgumentException e) {
          // expected: all 3 labels, as taxonomy facets return; actual: the child queue is sized topN
          throw new AssertionError("expected all 3 labels of dim, got " + e, e);
        }
        assertEquals(3, result.childCount);
      }
    }
  }
}
Command
cp $REPRO/TestSortedSetFacetsTopNMaxValue.java $LUCENE/lucene/facet/src/test/org/apache/lucene/facet/sortedset/
cd $LUCENE && ./gradlew :lucene:facet:test --tests org.apache.lucene.facet.sortedset.TestSortedSetFacetsTopNMaxValue -Ptests.seed=DEADBEEF -Ptests.asserts=true
# assertions off: -Ptests.asserts=false (same failure)
Expected
childCount 3: a (1), b (1), c (1), as getTopChildren(10, "dim") returns and as taxonomy facets give for Integer.MAX_VALUE.
Observed
IllegalArgumentException: maxSize must be >= 0 and < 2147483631; got: 2147483647 from AbstractSortedSetDocValueFacetCounts.java:325, with assertions on and off.

All files of this repro: repro/LFV-994/

More files, environment, full output292 words

The test indexes 3 documents with one SortedSetDocValuesFacetField("dim", label) each (a, b, c), counts MatchAllDocsQuery with SortedSetDocValuesFacetCounts and calls getTopChildren(Integer.MAX_VALUE, "dim"), expecting childCount 3. Single thread; every seed run gave the same failure (on main DEADBEEF and C0DECAFE with assertions on and off, 5EED1234 and 0DD5EED7 with them off, C0FFEE01 with them on; on the 10.6.0 jars DEADBEEF, C0DECAFE and 5EED1234 with both), although the test framework randomizes settings such as the Directory implementation. The IllegalArgumentException is caught once and rethrown as an AssertionError so that the message states expected against actual; the exception is kept as the cause. Set -Ptests.asserts explicitly: with seed DEADBEEF and no value, Lucene's build picks assertions off. Before it goes into a PR, ./gradlew tidy wraps one comment line that is longer than 100 characters; also use MatchAllDocsQuery.INSTANCE there, since new MatchAllDocsQuery() is deprecated on main and in 10.6.0 (the runs used the constructor; it does not affect the failure). The test needs the org.apache.lucene.tests framework and FacetsCollectorManager (recent releases); older releases were checked with release-portable main() programs.

Environment

lucenemain 645d4fe14a20 (11.0.0-SNAPSHOT); 10.6.0 and every release run back to 4.7.0 also fail (the releases in between by reading); 4.3.0 to 4.6.1 pass
jdkOpenJDK 25.0.3
osLinux aarch64

Observed output

TestSortedSetFacetsTopNMaxValue > testGetTopChildrenWithMaxValueTopN FAILED
    java.lang.AssertionError: expected all 3 labels of dim, got java.lang.IllegalArgumentException: maxSize must be >= 0 and < 2147483631; got: 2147483647
        at __randomizedtesting.SeedInfo.seed([DEADBEEF:3B208D4DB1BA11E3]:0)
        at org.apache.lucene.facet.sortedset.TestSortedSetFacetsTopNMaxValue.testGetTopChildrenWithMaxValueTopN(TestSortedSetFacetsTopNMaxValue.java:56)

        Caused by:
        java.lang.IllegalArgumentException: maxSize must be >= 0 and < 2147483631; got: 2147483647
            at org.apache.lucene.core@11.0.0-SNAPSHOT/org.apache.lucene.util.PriorityQueue.<init>(PriorityQueue.java:123)
            at org.apache.lucene.core@11.0.0-SNAPSHOT/org.apache.lucene.util.PriorityQueue.<init>(PriorityQueue.java:80)
            at org.apache.lucene.facet.TopOrdAndNumberQueue.<init>(TopOrdAndNumberQueue.java:42)
            at org.apache.lucene.facet.TopOrdAndIntQueue.<init>(TopOrdAndIntQueue.java:24)
            at org.apache.lucene.facet.sortedset.AbstractSortedSetDocValueFacetCounts.computeTopChildren(AbstractSortedSetDocValueFacetCounts.java:325)
            at org.apache.lucene.facet.sortedset.AbstractSortedSetDocValueFacetCounts.getTopChildrenForPath(AbstractSortedSetDocValueFacetCounts.java:300)
            at org.apache.lucene.facet.sortedset.AbstractSortedSetDocValueFacetCounts.getTopChildren(AbstractSortedSetDocValueFacetCounts.java:61)
            at org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetCounts.getTopChildren(SortedSetDocValuesFacetCounts.java:57)
            at org.apache.lucene.facet.sortedset.TestSortedSetFacetsTopNMaxValue.testGetTopChildrenWithMaxValueTopN(TestSortedSetFacetsTopNMaxValue.java:53)
1 test completed, 1 failed

# the same with -Ptests.asserts=false; the 10.6.0 release jars fail the same way with -ea and -da

Why it looks unintended

  • The only topN check, validateTopN, rejects just topN <= 0; no javadoc sets an upper bound.
  • Taxonomy facets cap the same queue at the taxonomy's size, and Lucene's taxonomy tests call getTopChildren(Integer.MAX_VALUE, ...); five more implementations cap too.
  • Up to 4.6.1 the API documented Integer.MAX_VALUE as "all children" and SSDV honoured it; the 4.7.0 rewrite capped only taxonomy.
The full argument296 words
  • The API accepts the value. validateTopN "checks if topN is valid for getTopChildren and getAllDims" and rejects only topN <= 0 (Facets.java:74-84); LUCENE-10467 (#751, 9.2) made that range consistent across implementations. getTopChildren "Returns the topN child labels under the specified path" (Facets.java:40-41).
  • The sibling implementation caps on purpose. Math.min(taxoReader.getSize(), topN) came with the LUCENE-5339 rewrite (189feaacb6f, Michael McCandless), in the same commit that ported the old Integer.MAX_VALUE test to taxonomy getTopChildren(Integer.MAX_VALUE, "dim"); it is still on main (TestTaxonomyFacetCounts.java:556, TestTaxonomyFacetCounts2.java:338, :343). FloatTaxonomyFacets, StringValueFacetCounts, LongValueFacetCounts, RangeFacetCounts, RangeOnRangeFacetCounts and MatchingFacetSetsCounts cap too.
  • A large top-n is the normal way to ask for every child. On #843 Yuting Gan (Yuti-G) wrote that callers keep getting all children "as long as the user specifies a large top-n"; on #974 Greg Miller (gsmiller) wrote that "getAllChildren is not identical behavior as getTopChildren with a huge top-n value", treating the latter as an ordinary call.
  • History. Up to 4.6.1 the FacetRequest javadoc (Shai Erera, LUCENE-5136) said: "If set to Integer.MAX_VALUE, all immediate child categories will be returned", and Michael McCandless's SSDV accumulator (LUCENE-4795) answered any request for at least the dim's label count, so Integer.MAX_VALUE too, as "all available results" without a queue. The LUCENE-5339 rewrite (4.7.0) dropped that for SSDV only; none of its comments (90 in the JIRA record, 89 on the migrated #6403), no CHANGES or MIGRATE entry and no test discusses an uncapped SSDV queue. Executed: 4.6.1 returns all labels, 4.7.0 throws.
  • Core precedent. LUCENE-4938 (#6002) fixed an IndexSearcher queue that was not capped at maxDoc (reported and fixed by Robert Muir; Michael McCandless and Uwe Schindler traced it), and on LUCENE-8542 (#9588) Michael McCandless called pre-allocating the full topN "really unexpected behavior".
The devil's-advocate check185 words

The strongest case for "works as designed": topN is a size the caller chooses; PriorityQueue documents that it pre-allocates and throws on purpose "to prevent confusing OOME"; Facets is @lucene.experimental; getAllChildren exists for "all children"; the sandbox TopnOrdinalIterator also sizes its queue from topN, with a TODO by its author Egor Potemkin (#13568) doubting the taxonomy getSize() cap for very large taxonomies; and the 4.7.0 redesign never repeated the "Integer.MAX_VALUE = all" promise.

Why it fails: validateTopN accepts the value; PriorityQueue is @lucene.internal and its message names an internal maxSize, not topN; getAllChildren is unordered ("Users should make no assumptions about ordering of the children") and has no getAllDims or getTopDims form, and both of those fail too; the same call works on taxonomy facets through a cap added in the same rewrite; and the TODO questions how loose that cap is, which argues for a tighter or lazily growing queue, not for failing. The redesign point is fair, so the history is best presented as a behaviour change in 4.7.0 rather than a broken promise. Verdict: not intended, a defect (low severity).

Suggested fix

Recommended A: cap the child queue at the field's label count (validated)

Cap the queue at the field's label count, as taxonomy facets cap theirs at the taxonomy's size: new TopOrdAndIntQueue(Math.min(topN, state.getSize())) at AbstractSortedSetDocValueFacetCounts.java:325. With it the repro and the whole facet module test suite (307 tests) pass. The cap is loose when the field has many labels and the dim few.

if (q == null) {
  // Lazy init, so we don't create this for the
  // sparse case unnecessarily
  // the path cannot have more children than the field has labels:
  q = new TopOrdAndIntQueue(Math.min(topN, state.getSize()));
}
All options and trade-offs4 options · 495 words

Option A was applied in two separate scratch worktrees of 645d4fe14a20 and run with gradle (both removed after the runs); the hunt's checks validated the same diff. Options B and C were not built.

A: cap the child queue at the field's label count (validated) (recommended)

One line in computeTopChildren (AbstractSortedSetDocValueFacetCounts.java:325), mirroring TaxonomyFacets.makeTopOrdAndNumberQueue (TaxonomyFacets.java:250-251).

if (q == null) {
  // Lazy init, so we don't create this for the
  // sparse case unnecessarily
  // the path cannot have more children than the field has labels:
  q = new TopOrdAndIntQueue(Math.min(topN, state.getSize()));
}

Trade-offs

  • A path's children are distinct ordinals of the field, so the queue never needs more than state.getSize() slots; results are unchanged for every topN that works today.
  • Loose when the field holds many labels and the dim few: by default all dims share one field, so a 3-label dim in a field with millions of labels still gets a queue of that size for Integer.MAX_VALUE (the same looseness as the taxonomy cap). The cross-model reviewer (OpenAI GPT-5.6) pointed this out.

What the checks validated

  • Gradle, stock 645d4fe14a20 (seed DEADBEEF), in two separate worktrees: the repro fails with -Ptests.asserts=true and false.
  • Gradle with the fix, the whole facet module (:lucene:facet:test, seed C0DE0994, assertions on): 40 classes (39 upstream and the repro), 307 tests, 0 failures, 7 skipped (tests a default run skips, e.g. the nightly group); the repro also passes with assertions off. :lucene:facet:checkGoogleJavaFormat passes on the fix.
  • First run, with the fix: the repro and TestSortedSetDocValuesFacets, TestDrillSideways, TestParallelDrillSideways, TestFacetQuery and TestFacetLabel, assertions on: 62 tests, 0 failures; the repro and TestSortedSetDocValuesFacets with assertions off and nightly tests on: 20 tests, 0 failures, 0 skipped.
  • The executed probe with the fix: Integer.MAX_VALUE returns the 3 labels, and 1 << 24 allocates 2,248 bytes instead of 67,111,104.
  • The hunt's checks: the finder's 6 tests and an independent reproducer's 10 tests pass; 7 upstream facet test classes (82 tests) pass with this fix and the sibling LFV-983 fix; the differential harness's saturation and allocation failures drop to 0.

B: cap at the path's own number of children (not built)

For a flat dim, ordRange.end() - ordRange.start() + 1; a hierarchical DimTree exposes only child iterators, so a child count would have to be computed or stored. Prompted by the cross-model reviewer's remark that A is loose.

Trade-offs

Removes the looseness of A; more code, and the hierarchical case needs new bookkeeping.

C: grow the queue lazily up to topN (not built)

Start small and grow only as children arrive, instead of allocating topN + 1 slots up front.

Trade-offs

Would help every top-N facet path, but core PriorityQueue has a fixed capacity, so it needs a different structure; larger than the bug needs.

Not recommended: reject large topN in validateTopN

Add an upper bound to Facets.validateTopN.

Trade-offs

Turns the working taxonomy call getTopChildren(Integer.MAX_VALUE, ...), and Lucene's own tests of it, into errors.

Downstream note

Services that pass a user-chosen facet size straight to SortedSetDocValues facets should cap it: values from 2,147,483,631 up fail, and large values below that reserve heap in proportion to the value.

How it was found

AI tools probing numeric limits passed Integer.MAX_VALUE as topN to SortedSetDocValues, taxonomy, string and long facets: only the SortedSetDocValues counts failed to return child labels (taxonomy's huge-topNDims failure is LFV-983). A model-based differential harness confirmed it on 40 random indexes; one minimal test reproduces it.

The method in full171 words

Method: non-formal first signal, then semi-formal checking (an executed probe, then model-based differential testing on the stock jars).

  • A planning AI tool for numeric-limit hunts read the facet code and ran a probe (FacetTopNProbe) on main a9779ef3c193, 10.5.2, 9.12.3 and the 10.6 release candidate: SSDV getTopChildren, getAllDims and getTopDims with Integer.MAX_VALUE threw, and topN = 10^8 allocated 381 MiB per dim.
  • The hunting AI tool wrote a reference model of top-N facet results (saturation: for topN at least the number of children, the result equals the result at topN = 1000; allocation bounded by the labels) and a differential harness over 40 seeded random indexes, 18 Facets constructions and 5 call shapes: 93,485 checks, of which 9,924 saturation and 3,060 allocation checks failed on stock main (including the sibling dim-queue sites, LFV-983) and 0 with both fixes. An SMT solver confirmed that exactly topN from 2,147,483,631 to 2,147,483,647 throws.
  • It reduced the case to a public-API JUnit with a taxonomy control, and later to the one-test repro.

Prior reports, history and checks

Prior reports

No prior report found in GitHub issues, PRs and commits (incl. the JIRA archive), the mailing lists, downstream trackers and code, the web, and all 414 open PRs; re-checked twice on 2026-10-30. Not fixed upstream: the file's last change is #16056 (2026-05-14, unrelated).

Searches5 searches

No report of this bug was found, and nothing upstream fixes it. The closest items are context: #6403 (LUCENE-5339, the rewrite that capped only the taxonomy queue); #843 and #974 (range-facet caps, and the remarks that a large top-n is how callers ask for every child); #133 and #11764 (other implementations' caps); #751 (the topN <= 0 check); #11586 (getAllChildren); #13568 (the sandbox TODO); #12862 (open, the only open PR touching the fix-site file; it does not touch the queue); the core precedents #6002 (LUCENE-4938) and #9588 (LUCENE-8542). The sibling LFV-983 is the same pattern at a different fix site, found by the same hunt.

What was searched, when, and what turned up
WhereWhenHowFound
GitHub issues, PRs, commits (apache/lucene incl. the migrated JIRA archive; apache/lucenenet, apache/solr, OpenSearch, Elasticsearch)2026-10-28 to 2026-10-29three automated passes of 51 queries each (queue sizing; 'all children' with Integer.MAX_VALUE; the cap inconsistency with taxonomy) plus 30 manual searches, e.g. computeTopChildren, TopOrdAndIntQueue maxSize, getAllDims Integer.MAX_VALUE, getTopChildren IllegalArgumentException maxSizeno report; context only (#6403, #843, #974, #751, #11586, #13568)
JIRA (LUCENE, LUCENENET, SOLR), mailing lists, web, downstream code2026-10-2922 JQL queries with 16 issues read in full; 24 lists.apache.org queries over dev@, java-user@, issues@; 18 web queries; GitHub code search for getTopChildren(Integer.MAX_VALUE / getAllDims(Integer.MAX_VALUE callersno report; downstream code uses the idiom on taxonomy and range facets only; a 2016 java-user thread proposes it on taxonomy facets
Open PRs and recent activity2026-10-29changed-file lists of all 414 open apache/lucene PRs; the 93 items updated since 2026-10-26; fix-site commits on main, branch_11x, branch_10x and branch_10_0 to branch_10_6only #12862 touches the file, not the queue; nothing about facet top-N sizing
Re-check for this page2026-10-30issue/PR search for computeTopChildren, getTopChildren with Integer.MAX_VALUE, facet issues created since 2026-10-29; last commits on the fix-site filenothing new; last change still #16056 (2026-05-14); upstream main 716d6f216f52
Second re-check for this page2026-10-30issue/PR search for computeTopChildren, getTopChildren with Integer.MAX_VALUE, TopOrdAndIntQueue maxSize, SortedSetDocValuesFacetCounts topN, facet issues created on 2026-10-30; commits on the fix-site file, lucene/facet and PriorityQueue.java since 2026-10-28nothing new (the topN query finds only the unrelated #518 and the getTopDims PR #747); last change still #16056; upstream main 2f424fd428da

History

Introduced by the LUCENE-5339 facet API rewrite (5458dbf2484, 2013-11-14), first released in 4.7.0. 4.3.0 to 4.6.1 return all labels for Integer.MAX_VALUE; 4.7.0 through 10.6.0 and main fail (18 version points run, the releases in between by reading). Only the exception type changes, with core PriorityQueue.

Versions tested9 rows

LUCENE-5339 "Simplify the facet module APIs" (#6403; Michael McCandless; feature-branch commit 5458dbf2484f, 2013-11-14; branch_4x port 7477fde1cb06 and trunk merge 9d0b60388da8, 2014-01-04; SVN-era patches, no PR) built the new SSDV child queue as new TopOrdCountQueue(topN) (renamed TopOrdAndIntQueue in f6cd7fda747). In the same series 189feaacb6f capped every taxonomy queue with Math.min(taxoReader.getSize(), topN) and ported the old Integer.MAX_VALUE test to taxonomy, and 92b1e230715 removed the old SSDV accumulator with its "all available results" branch. Later moves kept the expression: LUCENE-7811 (6.6.0, the concurrent counts), LUCENE-10325 (#747, 9.2.0, getTopDims), LUCENE-10585 (#915, 9.3.0, the shared base class).

The exception follows core PriorityQueue: IllegalArgumentException: maxSize must be <= 2147483391 in 4.7.0 to 4.9.0, NegativeArraySizeException: -2147483648 in 4.9.1 to 7.4.0 (LUCENE-5844 moved the + 1 ahead of the check), and the current message from 7.5.0 on (lucene-solr PR #411 by Raul Saavedra, merged by Michael McCandless). Versions from 4.3.0 to 10.5.2 and the 10.6.0 commit were run with release-portable main() programs on the same data (an SSDV dim and a taxonomy control with 3 labels); recent ones also with JUnit. All on OpenJDK 25.0.3, Linux aarch64. Releases between the executed ones are affected by reading.

Versions and branches executed, with results
Version or commitVerdictResult
main 645d4fe14a20 (unreleased 11.0) affectedfails, -ea and -da (gradle in two separate worktrees; standalone runner)
10.6.0 (4ae946e5a9b9) affectedfails, -ea and -da (minimal repro on the release jars, from computeTopChildren:332: the same expression, 7 lines lower than on main because main's #14761 is not in 10.6.0; history program 7 of 7 checks fail on the same commit)
10.5.2, 9.12.3, 9.2.0 affectedfail (history program 7 of 7, incl. getTopDims; JUnit 5 of 6 on 10.5.2 and 9.12.3)
9.1.0, 8.11.4, 7.7.3, 7.5.0 affectedfail, IllegalArgumentException (5 of 5)
7.4.0, 6.6.6, 6.6.0 affectedfail, NegativeArraySizeException, also in the concurrent counts (5 of 5)
5.5.5, 4.10.4, 4.9.1 affectedfail, NegativeArraySizeException (3 of 3)
4.9.0, 4.7.0 affectedfail, IllegalArgumentException 'maxSize must be <= 2147483391' (3 of 3); 64 MiB at 2^24
4.6.1, 4.6.0, 4.3.0 not affectedpass: all 3 labels for Integer.MAX_VALUE (pre-4.7 API), about 5.5 KB at 2^24
4.2.1 n/ano SortedSetDocValues faceting

Independent checks

The finder, an independent reproducer, an intended-behaviour devil's advocate, an adjudication, an audit, fact checks and two gradle runs for this page all reproduce it. Cross-model reviews (OpenAI GPT-5.6) could run nothing: one said real, the other not real for procedure only.

Checks and verdicts522 words

Every executing check ran on the stock jars and voted real. The only dissent is procedural: a cross-model refute review that could run no code voted not real on procedure only at low confidence while agreeing with the root cause and that the input is in contract.

Each independent check and its verdict
CheckVerdictWhat it found
Planning probe first signalSSDV getTopChildren, getAllDims and getTopDims with Integer.MAX_VALUE throw on main, 10.5.2, 9.12.3 and the 10.6 release candidate; 381 MiB per dim at 10^8.
Finder (finder) candidateDifferential harness (93,485 checks; its saturation and allocation failures drop to 0 with the fixes); JUnit 5 of 6 fail on main (-ea, -da), 10.5.2 and 9.12.3; taxonomy control passes; 6 of 6 with the fix.
Cross-model review, intended lens (OpenAI GPT-5.6, read-only) real, mediumRaised the sandbox TODO as a counter-signal and judged it weaker than the production evidence; a separate re-run fails 5 of 6.
Independent reproducer realOwn JUnit with flat, hierarchical and multi-valued dims in 2+ segments: 8 of 10 fail on main (-ea, -da), 10.5.2 and 9.12.3, including topN = 2,147,483,631; 67,110,272 vs 592 bytes; 10 of 10 with the fix.
Cross-model review, refute lens (OpenAI GPT-5.6, read-only) not real, low (procedural)It could not run any code, so it voted not real on procedure only; root cause agreed, input in contract; noted the fix's cap is loose. Separate re-runs fail 5 of 6.
Intended-behaviour devil's advocate real, highBuilt the strongest 'works as designed' case and rejected it; found the pre-4.7 'Integer.MAX_VALUE = all children' javadoc; re-runs fail on main and 10.5.2.
Adjudication confirmed, highRe-ran the independent reproduction's JUnit with a new seed: 8 of 10 fail with -ea and -da; controls pass.
History follow-up 4.7.0 first affectedRelease-portable programs: 4.3.0, 4.6.0 and 4.6.1 pass; 17 points from 4.7.0 to main fail.
Credibility audit keepRe-ran the finder's JUnit (-da, and -ea with a fresh seed): 5 of 6 fail; advised 'behaviour change in 4.7.0' wording.
Minimal repro verifiedOne test fails on 645d4fe14a20 with -ea, -da and a second seed; passes with the fix.
Fact check of the first version 2 narrow errors, fixedRe-ran the gradle repro (-ea, -da); its own probe showed the concurrent, DrillSideways, hierarchical, multi-valued and MAX_ARRAY_LENGTH shapes throw and the fix returning all labels.
Fact check of the revised version 3 narrow wording errors, fixedRe-ran the gradle repro in a fresh worktree (-ea, -da; passes with the fix) and the repro on the 10.6.0 release jars with a new seed (-ea, -da); its own probe showed the plain, concurrent and DrillSideways calls throw on main and return the labels with the fix.
This page's first run reproduced; fix validatedGradle stock fails (-ea, -da); 10.6.0 release jars fail (-ea, -da); with the fix 62 tests, then 20 with nightly tests, pass; format check passes.
This page's second run reproduced; fix validatedA fresh worktree: gradle stock fails (-ea, -da); with the fix the repro passes and the whole facet module (307 tests) passes; format check passes.

Diagram 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.

Sources and provenance

Finding record, Lucene and upstream sources, repro files and diagram notes1,523 words

Finding record

LFV-994, snapshot of 2026-11-06

Registry title
SortedSetDocValues facets size the child priority queue from topN instead of the number of labels, so getTopChildren, getAllDims and getTopDims(.., topNChildren) with topN = Integer.MAX_VALUE throw IllegalArgumentException where taxonomy facets return every label, and a large topN allocates topN + 1 queue slots even for a 3-label dim
Area
facet / SortedSetDocValues child queue (AbstractSortedSetDocValueFacetCounts.computeTopChildren, inherited by SortedSetDocValuesFacetCounts and ConcurrentSortedSetDocValuesFacetCounts)
Priority
Low, rank 643: SSDV getTopChildren and getAllDims fail loudly on the Integer.MAX_VALUE 'all children' idiom that taxonomy facets accept, a module bug that never returns wrong results, so it leads the new MAX_VALUE facet rows right after the GroupingSearch row LFV-964.
Impact class
wrong error
Impact note
Applications that call getTopChildren, getAllDims or getTopDims(.., topNChildren) on SortedSetDocValuesFacetCounts or ConcurrentSortedSetDocValuesFacetCounts (also through MultiFacets or DrillSideways for SSDV dims, by reading) with Integer.MAX_VALUE (or any topN >= 2147483631) as 'all children' get IllegalArgumentException 'maxSize must be >= 0 and < 2147483631' on every such call, where the same call on taxonomy facets returns every label, and with a large but legal topN pay a transient allocation of topN + 1 references per dim with hits however few labels exist (64 MiB at 2^24 on 3 labels); default FacetsConfig, codec and searcher, any index size, -ea and -da, every release from 4.7.0 to 10.6.0 and main; results for ordinary sizes are correct and nothing is written to the index.
Summary
You index a SortedSetDocValues facet dim with three labels and call getTopChildren(Integer.MAX_VALUE, dim) to get all of them, expecting the same result as getTopChildren(1000, dim), because Facets.validateTopN accepts every topN > 0 and taxonomy facets return all three labels for exactly this call. Instead AbstractSortedSetDocValueFacetCounts.computeTopChildren builds new TopOrdAndIntQueue(topN) without capping topN at the number of labels, so PriorityQueue throws IllegalArgumentException 'maxSize must be >= 0 and < 2147483631; got: 2147483647', and getAllDims(Integer.MAX_VALUE) and getTopDims(10, Integer.MAX_VALUE) fail the same way. Below that limit the same line pre-allocates topN + 1 slots: getTopChildren(2^24, dim) over 3 labels allocates about 64 MiB to return 3 results.
Introduced
5458dbf2484f398b710ce40296d98e19969bf3c0 ('LUCENE-5339: current patch', lucene5339 feature branch, svn r1542025, Michael McCandless): the rewritten SortedSetDocValuesFacetCounts builds its child queue as 'q = new TopOrdCountQueue(topN)' (renamed TopOrdAndIntQueue by f6cd7fda747); released through the branch_4x port 7477fde1cb06 ('LUCENE-5371, LUCENE-5339: ... simplify facet APIs', svn r1555342) and the trunk merge 9d0b60388da8. Issue LUCENE-5339 'Simplify the facet module APIs' (#6403); SVN-era patches, no pull request [read: git log -S/-G on the queue expression and blame at the 4.7.0 tag in the history clone; the release boundary is executed: 4.6.1 passes, 4.7.0 fails]. A regression: the pre-4.7 code it replaced (SortedSetDocValuesAccumulator, LUCENE-4795, removed by 92b1e230715) returned all children without a queue when numResults covered the ordinal range, and the pre-4.7 FacetRequest javadoc documented Integer.MAX_VALUE as 'all'; in the same rewrite 189feaacb6f capped every taxonomy queue with Math.min(taxoReader.getSize(), topN) and ported the Integer.MAX_VALUE test to taxonomy only. Later moves kept the expression: LUCENE-7811 (3e425d39873, ConcurrentSortedSetDocValuesFacetCounts, 6.6.0) and LUCENE-10585 (8db1e41fc072, #915, merge into AbstractSortedSetDocValueFacetCounts, 9.3.0). (2013-11-14 (5458dbf2484, feature branch; author date equals commit date); 2014-01-04 (7477fde1cb06, reached branch_4x))
First affected version
4.7.0 (tag 2014-02-25) [exec, -da: getTopChildren(Integer.MAX_VALUE) and getAllDims(Integer.MAX_VALUE) throw IllegalArgumentException 'maxSize must be <= 2147483391; got: 2147483647', getTopChildren(2^24) on 3 labels allocates 67,111,456 bytes, taxonomy control returns the 3 labels]; last unaffected 4.6.1 [exec: numResults = Integer.MAX_VALUE returns all children, 5,576 bytes at 2^24]; SortedSetDocValues faceting starts in 4.3.0 (4.3.0 and 4.6.0 also pass; 4.2.1 has no sortedset package)
Affected versions
every release from 4.7.0 to 10.5.2 (all 4.7.x-10.x lines), 10.6.0 (released 2026-10-29; run as its RC, branch_10_6 head 4ae946e5a9b9) and main a9779ef3c193; never fixed. [exec] follow-up history runs (release-portable main() on the core and facet jars, -da, JDK 25): 4.7.0, 4.9.0, 4.9.1, 4.10.4, 5.5.5, 6.6.0, 6.6.6, 7.4.0, 7.5.0, 7.7.3, 8.11.4, 9.1.0, 9.2.0, 9.12.3, 10.5.2, branch_10_6 and main all FAIL with the taxonomy control passing; the exception changes with core PriorityQueue (IllegalArgumentException 4.7.0-4.9.0, NegativeArraySizeException -2147483648 4.9.1-7.4.0, IllegalArgumentException 'maxSize must be >= 0 and < 2147483631' 7.5.0-main); ConcurrentSortedSetDocValuesFacetCounts is affected from 6.6.0 and getTopDims(.., topNChildren) from 9.2.0. The finder's JUnit on main (-ea, -da), 10.5.2 and 9.12.3; the independent reproduction's JUnit on main (-ea, -da), 10.5.2 and 9.12.3; the intended-behaviour check on main and 10.5.2. [read] the releases in between: git log -S/-G shows the uncapped queue expression unchanged in every SortedSetDocValues counts class since 2013 (moves only). Upstream main 645d4fe14a20 (2026-10-28) has no change at the fix site.
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 low-confidence “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
Upstream and prior reports
none found (2026-10-29, read-only; the prior-report record verdict new, plus the finder's search at 2026-10-28, the independent reproduction's and the intended-behaviour check's searches, the adjudication's and a recheck): three scripted prior-report searches (queue sizing, 'all children' with Integer.MAX_VALUE, cap inconsistency with taxonomy; 16 GitHub issue/PR, 3 commit, 2 downstream, 20 mailing-list over dev@, java-user@, issues@ and commits@, 4 JIRA-archive and 6 planned web queries each), 30 manual GitHub searches over apache/lucene, apache/lucenenet, apache/solr, OpenSearch and Elasticsearch, GitHub code search for downstream getTopChildren(Integer.MAX_VALUE / getAllDims(Integer.MAX_VALUE callers, 22 JIRA queries (LUCENE, LUCENENET, SOLR) with 16 issues read in full, 24 lists.apache.org queries, 18 web queries, the changed files of all 414 open apache/lucene PRs, all 93 items updated since 2026-10-26, and the fix-site commits on main, branch_11x, branch_10x and branch_10_0 to branch_10_6 by author and committer date. Recheck: 'computeTopChildren' and '"getTopChildren" "Integer.MAX_VALUE"' find no issue or PR; no item mentioning facet was updated since 2026-10-27; none of the 22 issues and PRs created since 2026-10-27 concerns facets (titles read); tracking issue #16937 does not mention facets; the last commit on AbstractSortedSetDocValueFacetCounts.java is dbf0d1426f13 (#16056, author and committer date 2026-05-14, an unrelated toArray cleanup); upstream main 645d4fe14a20 is 6 commits ahead of a9779ef3c193 and touches no lucene/facet file. Related, not this bug: #6403 (LUCENE-5339, the rewrite that capped only the taxonomy queue), #11574/#843 (LUCENE-10538) and #974 (LUCENE-10614, range-facet caps and remarks that a large top-n is the way to ask for all children), LUCENE-9950/#133 and #11764 (other implementations' caps), #11503/#751 (LUCENE-10467, the topN <= 0 check), #11586 (LUCENE-10550, getAllChildren), #12862 (open, the only open PR touching the fix-site file; does not touch the queue), #13568 (sandbox TopnOrdinalIterator, counter-signal TODO), and the core precedents #6002 (LUCENE-4938), #1581 (LUCENE-504), #9588 (LUCENE-8542), #7886 (LUCENE-6828).
Lucene commit tested
main 645d4fe14a20 (2026-10-28; the fix-site file is unchanged on upstream main 2f424fd428da, 2026-10-30): the minimal repro with gradle in two separate scratch worktrees, assertions on and off; with the fix, the repro and the whole facet module test suite (307 tests) and, in the first run, the SortedSetDocValues, drill-sideways, facet-query and facet-label test classes (assertions on) and the SortedSetDocValues test class with nightly tests (both worktrees removed after the runs); the standalone runner on main and on the 10.6.0 release jars with -ea and -da; an executed probe of the repro index (results and allocations, stock and with the fix); the earlier tests of the finder, an independent reproducer, a devil's advocate, an adjudication, an audit and fact checks on main a9779ef3c193 (no lucene/facet change up to 645d4fe14a20), 645d4fe14a20, 10.5.2 and 9.12.3; release-portable main() programs on releases from 4.3.0 to 10.5.2 and the 10.6.0 commit. OpenJDK 25.0.3, Linux aarch64.

Lucene and upstream sources

Finding record
  • lucene/facet/src/java/org/apache/lucene/facet/sortedset/AbstractSortedSetDocValueFacetCounts.java:320-326 (q = new TopOrdAndIntQueue(topN)); Facets.java:38-44 (getTopChildren javadoc) and :76-84 (validateTopN rejects only topN <= 0); taxonomy/TaxonomyFacets.java:250-251 (Math.min(taxoReader.getSize(), topN)); lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java:113-134
The finding in 30 seconds
  • Lucene main 645d4fe14a20: lucene/facet/src/java/org/apache/lucene/facet/sortedset/AbstractSortedSetDocValueFacetCounts.java:56-63, :112-140, :189-191, :226, :300-301, :309-339 (queue at :325)
  • Lucene main 645d4fe14a20: lucene/facet/src/java/org/apache/lucene/facet/Facets.java:39-44, :74-84; TopOrdAndIntQueue.java:23-25; TopOrdAndNumberQueue.java:41-43; taxonomy/TaxonomyFacets.java:250-251; sortedset/SortedSetDocValuesFacetCounts.java:57; sortedset/ConcurrentSortedSetDocValuesFacetCounts.java:52; sortedset/SortedSetDocValuesReaderState.java:164-165
  • Lucene main 645d4fe14a20: lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java:34, :39, :79-80, :113-134; lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java:32-34
Who is affected
  • Lucene main 645d4fe14a20: lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesFacetCounts.java:55, sortedset/ConcurrentSortedSetDocValuesFacetCounts.java:50 (@lucene.experimental)
  • Lucene main 645d4fe14a20: lucene/facet/src/java/org/apache/lucene/facet/sortedset/AbstractSortedSetDocValueFacetCounts.java:58-60, :115-117 (no counts: null / empty list), :319-325 (queue built at the first counted child); taxonomy/TaxonomyFacets.java:610-612 (dim queue, LFV-983)
Minimal repro
  • Lucene main 645d4fe14a20: lucene/core/src/java/org/apache/lucene/search/MatchAllDocsQuery.java:26, :31-34 (INSTANCE; the constructor is @Deprecated); the same at 4ae946e5a9b9 (10.6.0)
Why it looks unintended
  • Lucene main 645d4fe14a20: lucene/facet/src/java/org/apache/lucene/facet/Facets.java:33-34, :40-41, :74-84; taxonomy/TaxonomyFacets.java:250-251; taxonomy/TaxonomyReader.java:257-263 (getSize(): the number of categories, ancestors and the root included); taxonomy/FloatTaxonomyFacets.java:104; StringValueFacetCounts.java:180; LongValueFacetCounts.java:426; range/RangeFacetCounts.java:228; rangeonrange/RangeOnRangeFacetCounts.java:149; facetset/MatchingFacetSetsCounts.java:161
  • Lucene main 645d4fe14a20: lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyFacetCounts.java:556; TestTaxonomyFacetCounts2.java:338, :343; lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java:34, :39, :122; lucene/sandbox/src/java/org/apache/lucene/sandbox/facet/iterators/TopnOrdinalIterator.java:50-52
  • a Lucene clone releases/lucene-solr/4.6.1: lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java:86-89; lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java:227-228
Suggested fix
  • Lucene main 645d4fe14a20: lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacets.java:250-251; taxonomy/TaxonomyReader.java:257-263 (getSize(), the number of categories); sortedset/SortedSetDocValuesReaderState.java:47, :73-109
History
  • a Lucene clone releases/lucene-solr/4.7.0: lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesFacetCounts.java:120; taxonomy/IntTaxonomyFacets.java:102
  • a Lucene clone: git diff 4ae946e5a9b9 645d4fe14a20 -- lucene/facet/src/java/org/apache/lucene/facet/sortedset/AbstractSortedSetDocValueFacetCounts.java (+5/-12; a7704f5242d #14761 on main, not an ancestor of 4ae946e5a9b9)

Other statements trace to the hunt's working files (models, logs, reviews and briefs), which are not published.

Repro files

About the diagrams

Made in parallel with this page: a summary card (PNG), built from facts checked against the code, the minimal repro and an executed probe of the same index.

Built 2026-11-06 from the hunt's record of this finding and its doc file. Lucene main under test in this hunt: ea57360912ed. Every listed finding was re-run on Lucene main e1faeba08bde on 2026-11-02.