All findings · Lucene finding · LFV-984 · bpindexreorderer-javadoc-example-uses-removed-forkjoinpool-api

BPIndexReorderer's javadoc usage example calls setForkJoinPool and a 2-argument reorder, both removed

The "Typical usage" example in the BPIndexReorderer javadoc (lucene-misc) still calls reorderer.setForkJoinPool(pool) and the 2-argument reorder(reader, targetDir). Both went away when the thread pool became a third argument of reorder, so the copied example fails to compile on every release since 9.12.0.

Summary

Priority
Low, rank 1254The BPIndexReorderer 'Typical usage' example in lucene-misc calls removed APIs and fails loudly at compile time while the method javadoc is right, a niche-module doc defect.
Impact
minor
Since
9.12.0 (reorder); 10.0.0 (setForkJoinPool)introduced 2024-09-12 · about 2 years
Affected
9.12.0 to 10.6.0, and main (documentation only)
Status
documented
Found by
a compile check of javadoc code examples (non-formal)

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 example is a <pre> block in the class javadoc. Javadoc does not compile such blocks, so when the API changed nothing failed, and Lucene's own tests already use the new 3-argument call.

Summary card of the bug. The class javadoc's 'Typical usage' example calls reorderer.setForkJoinPool(pool), a method removed in 10.0.0, and reorderer.reorder(reader, targetDir) with 2 arguments, while the only reorder since 9.12.0 is reorder(CodecReader, Directory, Executor). javac rejects both calls. The fix is javadoc only: delete the setter line and pass pool as the third argument of reorder.
The javadoc example next to BPIndexReorderer's real API: setForkJoinPool is gone and reorder now takes the pool as a third argument. Select the still to open it at full size. Generated with AI, checked against the code.
  1. You want BP doc-id reordering and copy the class javadoc's "Typical usage": build a ForkJoinPool, call reorderer.setForkJoinPool(pool), then reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir).
  2. You expect the two calls to compile and the reordering to run on your pool, as they did on 9.8.0 to 9.11.1.
  3. Instead javac reports 2 errors on 10.0.0 to 10.6.0 and main: there is no method setForkJoinPool, and reorder needs 3 arguments (CodecReader, Directory, Executor), not 2. On 9.12.x only the reorder error appears, because the setter still exists there, deprecated.
  4. Why: in 2024 (#13289) the pool moved from the setter to the new third Executor argument of reorder; Lucene's tests were updated, this example was not. Delete the setter line and pass pool as the third argument, and both calls compile.

Who is affected

Developers adopting the opt-in BP reordering tool of lucene-misc who start from its class javadoc: the copied calls fail to compile every time, on every release since 9.12.0. Documentation only: nothing runs differently, and the method javadoc of reorder shows the right signature.

Mechanism, terms and numbers386 words

BPIndexReorderer (lucene-misc) renumbers documents with recursive graph bisection so that similar documents sit together, which shrinks postings and can speed up queries. Its class javadoc, after describing the algorithm, says "Typical usage would look like this:" (line 73) and gives a 14-line example. Two of its lines name API that no longer exists: reorderer.setForkJoinPool(pool); (removed in 10.0.0) and reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir) (the 2-argument form, removed in 9.12.0). The only public reorder is now reorder(CodecReader reader, Directory tempDir, Executor executor). Copied into a project, the two calls give cannot find symbol: method setForkJoinPool(java.util.concurrent.ForkJoinPool) and method reorder ... required: CodecReader,Directory,Executor; found: CodecReader,Directory on 10.0.0 to 10.6.0 and main, and the reorder error alone on 9.12.x. #13289 (2024-09-12) made both API changes and updated TestBPIndexReorderer to reorder(codecReader, dir, pool), but left the example. Passing the example's own pool as the third argument and deleting the setter line makes both calls compile; Lucene's 8 TestBPIndexReorderer tests pass with that javadoc change. Nothing in Lucene behaves wrongly; only the example is stale.

The example (main 645d4fe14a20, lines 73-90)

linetextexists?
76-77LeafReader reader;, Directory targetDir;placeholders
79Directory targetDir = FSDirectory.open(targetPath);yes (a second targetDir declaration; targetPath undeclared; side nit)
80BPIndexReorderer reorderer = new BPIndexReorderer();yes (line 110)
81-82ForkJoinPool pool = new ForkJoinPool(..., p -> new ForkJoinWorkerThread(p) {}, null, false);yes (JDK)
83reorderer.setForkJoinPool(pool);no (removed in 10.0.0)
84reorderer.setFields(Collections.singleton("body"));yes (line 141)
85CodecReader reorderedReaderView = reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir);no (2-argument form removed in 9.12.0)
86-89IndexWriter.addIndexes(reorderedReaderView), DirectoryReader.open(targetDir)yes

The real API

public CodecReader reorder(CodecReader reader, Directory tempDir, Executor executor) (line 838): "The provided Executor can be used to perform reordering concurrently. A value of null indicates that reordering should be performed in the current thread." and "The provided Executor must not reject tasks." A ForkJoinPool is an Executor, so the example's own pool fits the third argument unchanged. setForkJoinPool occurs nowhere under lucene/ except the javadoc line 83.

Why nothing caught it

Javadoc does not compile <pre> code and no test reads the example. TestBPIndexReorderer calls reorder(codecReader, dir, pool) (lines 122, 184) and reorder(codecReader, dir, null) (line 307).

Not claimed

That the block as a whole "does not compile": reader is never initialised, targetPath is undeclared and targetDir is declared twice; those are placeholders. The claim is about the two API calls.

Exposure and likelihood106 words
  • Who. Readers of the BPIndexReorderer class javadoc who copy its example, its only class-level usage guide. No query, document or index file reaches it.
  • Default vs opt-in. Opt-in: an expert, offline tool the application calls itself. No configuration or input changes the outcome: the copied calls always fail.
  • Scale. 1 error on 9.12.0 to 9.12.3, 2 errors on 10.0.0 to 10.6.0 and main.
  • Effect. A compile error, not wrong behaviour. The 9.12.x deprecation note on setForkJoinPool pointed to the 3-argument reorder; it went with the method in 10.0.0.
  • Priority. Low; the same kind of defect as the other stale javadoc examples of the same sweep.

Minimal repro

One JUnit class with one test. It compiles the example's two calls, copied verbatim, with javax.tools against the jars on the test class path, inside a method that declares reader, targetDir and pool, so every error is an API error. Nothing in Lucene runs, and nothing is random.

TestBPIndexReordererJavadocExample.java (one test, public API)65 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.misc.index;

import java.net.URI;
import java.util.List;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import org.apache.lucene.tests.util.LuceneTestCase;

public class TestBPIndexReordererJavadocExample extends LuceneTestCase {

  public void testClassJavadocExampleCalls() throws Exception {
    // expected: the class javadoc example's two reorderer calls compile; actual: both APIs are gone
    String source =
        """
        import java.util.concurrent.ForkJoinPool;
        import org.apache.lucene.index.*;
        import org.apache.lucene.misc.index.BPIndexReorderer;
        import org.apache.lucene.store.Directory;

        class Example {
          CodecReader run(LeafReader reader, Directory targetDir, ForkJoinPool pool)
              throws Exception {
            BPIndexReorderer reorderer = new BPIndexReorderer();
            reorderer.setForkJoinPool(pool);
            return reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir);
          }
        }
        """;
    JavaFileObject file =
        new SimpleJavaFileObject(URI.create("string:///Example.java"), JavaFileObject.Kind.SOURCE) {
          @Override
          public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return source;
          }
        };
    JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
    List<String> options =
        List.of(
            "-classpath", System.getProperty("java.class.path"),
            "-d", createTempDir().toString(),
            "-proc:none");
    boolean compiled = javac.getTask(null, null, diagnostics, options, null, List.of(file)).call();
    assertTrue("javac errors: " + diagnostics.getDiagnostics(), compiled);
  }
}
Command
# $LUCENE: a built checkout (./gradlew jar); $REPRO: the directory holding org/apache/lucene/misc/index/Test...java
# $DEPS: junit 4.13.2, randomizedtesting-runner 2.9.2, hamcrest 3.0
V=11.0.0-SNAPSHOT
CP=$LUCENE/lucene/core/build/libs/lucene-core-$V.jar:$LUCENE/lucene/codecs/build/libs/lucene-codecs-$V.jar:$LUCENE/lucene/test-framework/build/libs/lucene-test-framework-$V.jar:$LUCENE/lucene/misc/build/libs/lucene-misc-$V.jar:$DEPS
javac -d out -cp "$CP" $REPRO/org/apache/lucene/misc/index/TestBPIndexReordererJavadocExample.java
java -ea -Dtests.seed=DEADBEEF -cp "out:$CP" org.junit.runner.JUnitCore org.apache.lucene.misc.index.TestBPIndexReordererJavadocExample
# assertions off, same result: java -da -Dtests.asserts=false ...
Expected
The example's two reorderer calls compile.
Observed
Two javac errors on main and 10.6.0, with assertions on and off: no method setForkJoinPool(ForkJoinPool), and reorder requires (CodecReader, Directory, Executor) but got 2 arguments.

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

More files, environment, full output314 words

The two calls in the test were checked mechanically against BPIndexReorderer.java:83 and :85 at 645d4fe14a20: they are verbatim. /Example.java:10 and :11 in the output are those two lines.

Inside a Lucene checkout with gradle (./gradlew :lucene:misc:test --tests org.apache.lucene.misc.index.TestBPIndexReordererJavadocExample), the test as written fails for a class-path reason ("package org.apache.lucene.index does not exist"): Lucene's gradle test task runs lucene-core from the module path, which java.class.path does not include. Adding System.getProperty("jdk.module.path") to javac's -classpath fixes that; it then reports exactly the two errors below under gradle too (checked; the fixed twin passes under gradle).

No separate regression test is suggested: this test copies the example's calls, so it would not notice a later edit of the javadoc, and Lucene has no harness that compiles javadoc examples. TestBPIndexReorderer already exercises the 3-argument call with a pool.

Environment

lucenemain 645d4fe14a20 (11.0.0-SNAPSHOT); the 10.6.0 and 10.0.0 release jars give the same 2 errors, 9.12.0 the reorder error only, 9.11.1 passes
jdkOpenJDK 25.0.3 (build 25.0.3+9-LTS)
osLinux aarch64 (a compile-only check: on any JDK 15 or later, which the test's text block needs, the two API errors do not depend on the platform)

Observed output

# the command above, main 645d4fe14a20, seed DEADBEEF, -ea (-da identical); header lines (JUnit banner, vectorization warning, NOTE lines, Time: 1.86) left out, ... = remaining runner frames
There was 1 failure:
1) testClassJavadocExampleCalls(org.apache.lucene.misc.index.TestBPIndexReordererJavadocExample)
java.lang.AssertionError: javac errors: [/Example.java:10: error: cannot find symbol
    reorderer.setForkJoinPool(pool);
             ^
  symbol:   method setForkJoinPool(java.util.concurrent.ForkJoinPool)
  location: variable reorderer of type org.apache.lucene.misc.index.BPIndexReorderer, /Example.java:11: error: method reorder in class org.apache.lucene.misc.index.BPIndexReorderer cannot be applied to given types;
    return reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir);
                    ^
  required: org.apache.lucene.index.CodecReader,org.apache.lucene.store.Directory,java.util.concurrent.Executor
  found:    org.apache.lucene.index.CodecReader,org.apache.lucene.store.Directory
  reason: actual and formal argument lists differ in length]
	at __randomizedtesting.SeedInfo.seed([DEADBEEF:6C73A58A0D93465A]:0)
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.assertTrue(Assert.java:42)
	at org.apache.lucene.misc.index.TestBPIndexReordererJavadocExample.testClassJavadocExampleCalls(TestBPIndexReordererJavadocExample.java:63)
	...
FAILURES!!!
Tests run: 1,  Failures: 1

# 10.6.0 and 10.0.0 release jars, -da: the same 2 errors; 9.12.0: only the reorder error (plus javac's deprecation note); 9.11.1: passes

Why it looks unintended

  • The block is introduced as "Typical usage would look like this:", and its two calls compiled verbatim on 9.8.0 to 9.11.1.
  • #13289 gave reorder an Executor argument and updated Lucene's tests to reorder(codecReader, dir, pool), but not this example; no CHANGES or MIGRATE entry mentions it.
  • Lucene has fixed stale javadoc examples before as ordinary doc fixes (LUCENE-9046, #12693).
The full argument178 words
  • Offered as working code. "Typical usage would look like this:" (line 73), with no pseudo-code marker.
  • Maintained as real code. #12568 (36432fa6724, 2023-09-19) replaced setForkJoinPool(ForkJoinPool.commonPool()) with the custom-factory pool, and 1d0edd76a5e ("Fix compilation under Java 11.", the same day) escaped the lambda's -> in it as -&gt; (the Java 11 problem of that day's dev@ thread) and replaced a test-only random().nextBoolean() with false.
  • The API change forgot it. #13289 (ff8b81afc59, Adrien Grand, 2024-09-12) removed setForkJoinPool on main (deprecated it on branch_9x: "Pass an executor to reorder(CodecReader, Directory, Executor) instead") and gave reorder the Executor argument. It updated TestBPIndexReorderer from setForkJoinPool(pool) + reorder(codecReader, dir) to reorder(codecReader, dir, pool); none of its hunks touches the class javadoc, and its discussion never mentions it.
  • Public API. The class is public, in an exported package, with no @lucene.experimental or @lucene.internal tag.
  • Precedent. LUCENE-9046 "Fix wrong example in Javadoc of TermInSetQuery"; #12693 "chore: update the Javadoc example in Analyzer" (2023-10-18); LUCENE-7763 removed an outdated javadoc comment (LUCENE-9046 and LUCENE-7763 were found by the cross-model reviewer, OpenAI GPT-5.6).
The devil's-advocate check120 words

Strongest case for "not a bug": the block is illustrative pseudo-code. It never compiled as written (reader uninitialised, targetPath undeclared, targetDir declared twice), Lucene does not compile javadoc snippets, lucene-misc changes freely, the error is loud and the method javadoc is right.

Why it fails: it explains the placeholders, not two exact method calls. A reader supplies reader and targetPath; no context makes a removed method compile. The calls were edited as real code, compiled verbatim until 9.11.1, and broke only because #13289 changed the API without touching the example. The verifiers and the adjudication called it real (the refute lens could not run anything; its "not real" is procedural); the adjudication rated it a Low documentation defect.

Suggested fix

Recommended Pass the pool to reorder (validated)

Javadoc only: delete reorderer.setForkJoinPool(pool); and pass the pool as the third argument, reorder(SlowCodecReaderWrapper.wrap(reader), targetDir, pool), the same change #13289 made in Lucene's tests. Validated: the patched calls compile on main and 10.6.0, and TestBPIndexReorderer (8 tests) passes.

- * reorderer.setForkJoinPool(pool);
  * reorderer.setFields(Collections.singleton("body"));
- * CodecReader reorderedReaderView = reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir);
+ * CodecReader reorderedReaderView = reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir, pool);
All options and trade-offs3 options · 422 words

One fix was validated, with the javadoc diff applied to 645d4fe14a20; the optional extras were not run.

Pass the pool to reorder (validated) (recommended)

Javadoc only, lucene/misc/src/java/org/apache/lucene/misc/index/BPIndexReorderer.java:83 and :85. A narrow API-drift fix: it makes the two calls compile, while the block keeps its placeholders (reader, targetPath, the duplicate targetDir, no imports), so it is still not a self-contained compilation unit.

- * reorderer.setForkJoinPool(pool);
  * reorderer.setFields(Collections.singleton("body"));
- * CodecReader reorderedReaderView = reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir);
+ * CodecReader reorderedReaderView = reorderer.reorder(SlowCodecReaderWrapper.wrap(reader), targetDir, pool);

Trade-offs

None for users: documentation only. It keeps the pool as written (the devil's-advocate verifier's point); its custom thread factory came from #12568 ("Fix issues with BP tests and the security manager."), and whether the example still needs it is a separate question. reorder needs an Executor that does not reject tasks (line 834), which a live ForkJoinPool satisfies; the example never shuts the pool down (the devil's-advocate verifier's run did), and a pool.shutdown() after use would be optional polish (not run).

What the checks validated

  • The minimal test with its two calls taken mechanically from the patched javadoc passes 1 of 1: plain javac/java on main with assertions on and off, standalone on main (on and off) and on the 10.6.0 jars, and under ./gradlew :lucene:misc:test (gradle form). The stock calls fail the same test, so it detects the bug.
  • ./gradlew :lucene:misc:test --tests org.apache.lucene.misc.index.TestBPIndexReorderer -Ptests.seed=DEADBEEF: 8 tests, 0 failures.
  • ./gradlew :lucene:misc:checkGoogleJavaFormat and :lucene:misc:renderJavadoc pass; the rendered class page shows the 3-argument call and no setForkJoinPool.
  • At runtime, the devil's-advocate verifier ran the corrected calls on a real 200-document index on an earlier main with the same file: addIndexes and DirectoryReader.open succeed and all 200 ids survive.

Also tidy the placeholders (optional, not run)

Replace line 77 Directory targetDir; // Directory where to write the reordered index with Path targetPath; // where to write the reordered index: this removes the duplicate targetDir declaration and declares targetPath in one line.

Trade-offs

The adjudication's fix sketch includes removing the duplicate Directory targetDir; line, as a side nit the claim does not rest on.

Say that the second argument is a temporary directory (optional, not run)

The parameter is tempDir; the example passes targetDir, which works but may surprise. reorder writes its temporary files through a TrackingDirectoryWrapper over that directory (line 850) and deletes them before it returns (line 896; line 900 on failure). A short trailing comment, or a separate temporary directory, would make the contract explicit.

Trade-offs

Documentation only; no behaviour change.

How it was found

No formal method. A sweep compiled every Java code block in the non-sandbox javadocs against the main jars and flagged this block with cannot find symbol: method setForkJoinPool; a targeted test then found the reorder error too. Independent verifiers reproduced it with their own tests.

The method in full69 words
  • Sweep. A hunt unit for javadoc examples (siblings of another contributor's fix #16904) compiled every <pre><code class="language-java"> block of the non-sandbox lucene/**/src/java files with javax.tools against the stock main jars and flagged this block (2026-10-28).
  • Targeted test. A public-API JUnit compiled the block verbatim, declaring only the undeclared name targetPath and counting only API-level errors; it found both errors and the version split.
  • Tier. Non-formal: it compiles documentation code.

Prior reports, history and checks

Prior reports

No prior report found: GitHub issues and PRs, commits, the dev@, java-user@ and issues@ lists, downstream repositories and the web were searched on 2026-10-29; re-checked 2026-11-01. setForkJoinPool matches no Lucene issue or PR; no open or recent PR changes the example.

Searches3 searches

Related, not reports: #13289 made the example stale (its discussion never mentions it); #12489 and #12568 wrote it (its calls valid then); the dev@ thread of 2023-09-19 on #12568 (Uwe Schindler and Adrien Grand) is about a different, fixed Java 11 compile problem in this block; castorini/anserini#2289 is a 2023 usage snippet, valid then. The JIRA archive cannot hold a report: the class postdates the migration.

Others are filing stale-javadoc fixes in other files (#16904 and a series of issues).

What was searched, when, and what turned up
WhereWhenHowFound
Scripted searches, 2 runs2026-10-2951 queries each (class and method names, error text, javadoc/example phrasings) over GitHub issues, PRs and commits, downstream repositories, dev@, java-user@, issues@ and the JIRA archive, plus the web0 high hits
GitHub and lists, manual2026-10-2940 search phrasings; the changed files of all 414 open PRs; the full conversation and reviews of #13289; lists.apache.org3 open PRs touch the file, none the example block; only the 2023 dev@ thread on a different defect
Re-check2026-11-01issue and PR search for BPIndexReorderer, setForkJoinPool, "BPIndexReorderer javadoc"; the changed files of all 52 PRs updated since 2026-10-29; the file on main, branch_11x and branch_10_6the same 7 unrelated items, 0, 0; no PR changes the file; both stale lines still on every branch

History

The example was written in 2023 (#12489, #12568) and was right until #13289 (2024-09-12) changed the API: the 9.x backport removed the 2-argument reorder in 9.12.0 and deprecated setForkJoinPool, which 10.0.0 removed.

Versions tested6 rows
  • Written: 39f3777886c (#12489, 2023-09-14, the class and the reorder line; first released in 9.8.0) and 36432fa6724 (#12568, 2023-09-19, the pool and setter lines).
  • Made stale: ff8b81afc59 on main (released in 10.0.0) and the backport a2290ecb237 on branch_9x (released in 9.12.0), both #13289 by Adrien Grand, author date 2024-09-12. On branch_9x setForkJoinPool stayed as @Deprecated, so 9.12.x fails on reorder only.
  • Since then: only markup changes (378ca8d1bbf, #15573, 2026-01-15); the example text is identical at every release tag from 9.8.0 to 10.6.0 and on main.
Versions and branches executed, with results
Version or commitVerdictResult
main 645d4fe14a20; upstream main f815e679bf6c affectedfails with 2 errors, -ea and -da (upstream main read, not run: the file is byte-identical)
10.6.0 affectedfails with 2 errors (release jars, -da; -ea too in the fact check)
10.0.0 to 10.5.2 affectedfails with 2 errors (10.0.0 and 10.5.2 run)
9.12.0 to 9.12.3 1 errorfails on reorder only; setForkJoinPool still exists, deprecated (9.12.0 and 9.12.3 run)
9.8.0 to 9.11.1 not affectedboth calls compile (9.8.0 and 9.11.1 run)
before 9.8.0 no such classnot affected: BPIndexReorderer does not exist there

Independent checks

A finder, an independent reproducer, a reviewer from another model family (OpenAI GPT-5.6) with lenses (reading only), a devil's-advocate check, an adjudication and an audit. Every check that ran code reproduced it; the adjudication confirmed it with high confidence as a Low documentation defect.

Checks and verdicts165 words

The cross-model reviews could not run code.

Each independent check and its verdict
CheckVerdictWhat it found
Finder reproduced (doc)Compile sweep, then a JUnit compiling the whole block: fails on main (-ea, -da), 10.5.2, and 9.12.3 (reorder only).
Refute lens (OpenAI GPT-5.6) not a valid reviewReading only; its "not real" is procedural, as its own notes say.
Reproducer realOwn test with a corrected control: fails on main, 10.5.2, 10.0.0, 9.12.3, 9.12.0; 9.11.1 is the inverse control.
Intended lens (OpenAI GPT-5.6) real, mediumThe pseudo-code argument is weak; found the LUCENE-9046 and LUCENE-7763 precedents.
Devil's advocate real, highThree controls pass; ran the corrected calls on a real 200-document index.
Adjudication and audit confirmed (high), minorRe-ran with new seeds on main (-ea, -da); 9.11.1 inverse control.
Brief verified; fix validatedMinimal test fails on main (-ea, -da), 10.6.0, 10.0.0 and 9.12.0 (1 error), passes on 9.11.1; the patched calls pass; the module's TestBPIndexReorderer 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,344 words

Finding record

LFV-984, snapshot of 2026-11-06

Registry title
BPIndexReorderer's class javadoc 'Typical usage' example calls reorderer.setForkJoinPool(pool), removed in 10.0.0, and the 2-argument reorder(reader, targetDir), removed in 9.12.0, so it names APIs that no longer exist; #13289 moved the class to an Executor argument, reorder(CodecReader, Directory, Executor), and left the example unchanged (documentation defect)
Area
misc / index reordering (BPIndexReorderer class javadoc example)
Priority
Low, rank 1254: The BPIndexReorderer 'Typical usage' example in lucene-misc calls removed APIs and fails loudly at compile time while the method javadoc is right, a niche-module doc defect.
Impact class
minor
Impact note
Documentation only, with no runtime effect: a developer who adopts the opt-in BP doc-id reordering tool of lucene-misc by copying its class javadoc example gets compile errors on every release since 9.12.0 (1 on 9.12.x, where only the reorder call fails; 2 on 10.0.0 through 10.6.0 and main) and has to find the Executor-based signature in the method javadoc; nothing wrong ever runs, and no scale or special input is involved.
Summary
The BPIndexReorderer javadoc shows 'typical usage': build a ForkJoinPool, hand it to reorderer.setForkJoinPool(pool), then call reorderer.reorder(reader, targetDir). If you copy that into your code it does not compile on any release since 9.12.0: setForkJoinPool no longer exists (removed in 10.0.0) and reorder now needs a third argument, the Executor to run on. Passing the same pool as that third argument (and deleting the setter line) compiles and works, so only the code shown in the javadoc is wrong.
Introduced
ff8b81afc59 (#13289 'Integrate merge-time index reordering with the intra-merge executor.', by jpountz, author date = merge date 2024-09-12; branch_9x backport a2290ecb237, same author date): it replaced reorder(CodecReader, Directory) by reorder(CodecReader, Directory, Executor) and removed setForkJoinPool on main (on branch_9x it kept setForkJoinPool as @Deprecated, 'Pass an executor to reorder(CodecReader, Directory, Executor) instead'), updated TestBPIndexReorderer, and left the class javadoc example as it was (none of its hunks touches the example; no CHANGES or MIGRATE entry). The example itself dates from 39f3777886c (#12489, 2023-09-14, the reorder line) and 36432fa6724 (#12568, 2023-09-19, the setForkJoinPool(pool) line), both valid when written [read: git log, git blame and git show in the full-history clone; exec: release sweep, see affected_versions] (2024-09-12 (ff8b81afc59, #13289, author and merge date; the branch_9x backport a2290ecb237 has the same author date))
First affected version
9.12.0 [exec] (only the 2-argument reorder fails there; setForkJoinPool still exists, deprecated); 10.0.0 [exec] is the first release where both calls fail
Affected versions
9.12.0-9.12.3 (1 broken call: reorder), every 10.x release from 10.0.0 to 10.5.2 (2 broken calls: setForkJoinPool and reorder), 10.6.0 (released 2026-10-29; branch_10_6 4ae946e5a9b) [exec 2026-11-01: the minimal test fails on the 10.6.0 release jars with assertions on and off, 2 errors] and main a9779ef3c193; not affected: 9.8.0-9.11.1 (the verbatim example compiles; the class did not exist before 9.8.0). Not fixed upstream: main 645d4fe14a20, branch_11x, branch_10_6 and branch_10x still carry both stale lines (2026-10-29). [exec: the finder's JUnit fails on main (-ea and -da), 10.5.2, 10.0.0, 9.12.3 and 9.12.0 and passes on 9.11.1 and 9.8.0 (the follow-up's release sweep); the independent reproduction's JUnit, with a corrected-example control, fails on main (-ea and -da), 10.5.2 (-ea and -da), 10.0.0, 9.12.3 and 9.12.0, while on 9.11.1 the verbatim example compiles and the corrected one does not] [read: the example text is identical at every tag from 9.8.0 to 10.5.2 and on main (extracted, entity-decoded and diffed per tag), and the API presence was tabulated per tag: setForkJoinPool 9.8.0-9.12.3, reorder(CodecReader, Directory) 9.8.0-9.11.1]. Caveat: all runs used JDK 25 on Linux aarch64.
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
Upstream and prior reports
none found (searched 2026-10-29 and rechecked the same day): two scripted search runs (51 queries each over GitHub issues, PRs and commits, downstream repositories, the dev@, java-user@ and issues@ lists, the JIRA archive and the web; 0 high hits), 40 GitHub search phrasings (class and method names, 'reorderedReaderView', 'Typical usage would look like this', javadoc/example/stale/'does not compile' variants, the recent javadoc-fix authors), the changed files of all 414 open apache/lucene PRs (three, #15430, #13186 and #16847, touch BPIndexReorderer.java, none of them lines 73-91), the 93 issues and PRs created since 2026-10-25, the full conversation and reviews of #13289 (the example is never mentioned), lists.apache.org and 6 web searches. The JIRA archive cannot hold a report (the class was added in 2023-09, after the JIRA migration). Read but not the same bug: #13289 (the change that made the example stale), #12489 and #12568 (they wrote the example, valid then), the dev@ thread of 2023-09-19 on #12568 (Uwe Schindler and Adrien Grand on a different, fixed Java 11 compile problem in this block), castorini/anserini#2289 (a 2023 usage snippet, valid then), #16729, #12721, #13565, #12665, #12622, #12645, #14097, and the parallel outside javadoc series (hidingmyname #16821-#16828, #16920-#16922, #16927-#16936; Deepcodr #16904), none of which covers lucene/misc. Recheck: the 35 issues and PRs updated since 2026-10-28 name neither the class nor the API, and none of their 27 PRs changes BPIndexReorderer.java (#16919 and #16571 touch other misc/index files); search 'setForkJoinPool' and 'BPIndexReorderer javadoc' return 0; the file's latest upstream commit by author date is 54283150a81 (#16255, 2026-06-14); main 645d4fe14a20, branch_11x, branch_10_6 and branch_10x still carry both stale lines. Tracking issue #16937 does not name it.
Lucene commit tested
main 645d4fe14a20 (2026-10-28): the minimal test fails with assertions on and off (standalone, with a plain javac/java command); the 10.6.0 and 10.0.0 release jars give the same 2 errors, 9.12.0 the reorder error only, and on 9.11.1 the test passes. The fix was checked with the javadoc diff applied to 645d4fe14a20: the patched calls compile on main and on 10.6.0; ./gradlew :lucene:misc:test --tests TestBPIndexReorderer (8 tests), :lucene:misc:checkGoogleJavaFormat and :lucene:misc:renderJavadoc pass. Upstream main f815e679bf6c (2026-11-01) was read, not run: the file is byte-identical.

Lucene and upstream sources

Finding record
  • lucene/misc/src/java/org/apache/lucene/misc/index/BPIndexReorderer.java:73-91 (class javadoc 'Typical usage would look like this:' and the example; :77 and :79 the duplicate targetDir, :83 setForkJoinPool(pool), :85 the 2-argument reorder) and :838 (the only public reorder: reorder(CodecReader reader, Directory tempDir, Executor executor)); setForkJoinPool occurs nowhere else under lucene/
The finding in 30 seconds
  • a Lucene main checkout (645d4fe14a20) lucene/misc/src/java/org/apache/lucene/misc/index/BPIndexReorderer.java:73-90 (the example; :83 setForkJoinPool, :85 2-argument reorder; :77 and :79 targetDir), :110 (constructor), :141 (setFields), :825-838 (reorder(CodecReader, Directory, Executor) and its javadoc), :779 (computeDocMap)
  • a Lucene main checkout (645d4fe14a20) lucene/misc/src/test/org/apache/lucene/misc/index/TestBPIndexReorderer.java:57-58 (thread factory comment), :122, :184 (reorder(codecReader, dir, pool)), :307 (reorder(codecReader, dir, null))
  • a Lucene main checkout (645d4fe14a20): grep for setForkJoinPool over lucene/ (only BPIndexReorderer.java:83)
Why it looks unintended
  • a Lucene main checkout (645d4fe14a20) lucene/misc/src/java/org/apache/lucene/misc/index/BPIndexReorderer.java:73
  • a Lucene main checkout (645d4fe14a20) lucene/misc/src/java/module-info.java:24 (exports org.apache.lucene.misc.index); lucene/CHANGES.txt:6147 (LUCENE-9046), :8358 (LUCENE-7763); grep of CHANGES.txt and MIGRATE.md for 13289, BPIndexReorderer, setForkJoinPool (no hit)
Suggested fix
  • a Lucene main checkout (645d4fe14a20) lucene/misc/src/java/org/apache/lucene/misc/index/BPIndexReorderer.java:834 (the Executor must not reject tasks), :850, :896, :900 (temporary files tracked and deleted)
  • a Lucene main checkout (645d4fe14a20) lucene/misc/src/test/org/apache/lucene/misc/index/TestBPIndexReorderer.java:122, :184 (#13289's own update)

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 doc from the mechanism in the brief; the PNG is the summary frame. Its numbers come from its own probe on main: javac on the copied calls, and the fixed example run on a 10,000-document test index whose body alternates between even and odd by id. "16 runs instead of 10,000" counts maximal runs of consecutive documents of the same parity after reordering (10,000 before). In its release row, 9.7.0 ("no such class") and 10.6.0 ("2, by reading") were read at their tags, not compiled by that probe; this doc's runs compiled the test against the 10.6.0 jars (2 errors).

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.