One javadoc example names two constructors that no longer exist.
MemoryIndex(lucene-memory) holds exactly one document in memory. You add fields with anAnalyzerand callsearch(query), which returns a score above 0 when the document matches. The highlighter and monitor modules build on it.- Before 5.0, Lucene analyzers and the classic
QueryParsertook aVersion("matchVersion") argument. LUCENE-5859 removed those constructors: today it isnew SimpleAnalyzer()andnew QueryParser(field, analyzer).
SimpleAnalyzer() and QueryParser(String, Analyzer) exist, so javac rejects both lines. Select the still to open it at full size. Generated with AI, checked against the code.- You copy the 12-line "Example Usage" program from the
MemoryIndexjavadoc. It indexes two fields, parses+author:james +salmon~ +fish* manual~and prints "it's a match". - You add the 5 imports, declare
version(the block never does) and compile against 10.6.0 or main. You expect it to compile and print "it's a match". - Instead javac stops with 2 errors: in line 1,
SimpleAnalyzertakes no arguments; in line 5, there is noQueryParser(Version, String, Analyzer). Both errors are about the number of arguments, so no type forversionhelps. - Why: LUCENE-5859 removed both
Versionconstructors in 5.0.0 and updated the module's test, but not this example. 4.10.4 still compiles it; 5.0.0 through 10.6.0 and main do not. - Remove the two
versionarguments and the same 12 lines compile and print "it's a match" (score 1.3487055). Nothing wrong ever runs: it is a documentation fix.
Anyone who learns MemoryIndex from its javadoc and copies its only usage example, on every release since 5.0.0: two compile errors, with no configuration or special input involved. Nothing wrong ever runs, and javac lists the right constructors, so it is a Low documentation fix.
Mechanism, terms and numbers431 words
MemoryIndex is Lucene's one-document, in-memory index, often used to check whether a single text matches a query. Its class javadoc has one end-to-end "Example Usage" program: build a SimpleAnalyzer, add a "content" and an "author" field, parse +author:james +salmon~ +fish* manual~ with the classic QueryParser and print "it's a match". The program's first line is new SimpleAnalyzer(version) and its fifth is new QueryParser(version, "content", analyzer). LUCENE-5859 removed both Version-taking constructors (trunk 2014; released in 5.0.0 through the branch_5x backport) and left this example, so it has not compiled on any release since 5.0.0: with the Lucene imports, both calls pass the wrong number of arguments, whatever version is declared as. With the two version arguments dropped it compiles and prints "it's a match" on main and 10.5.2. Documentation only: no code is wrong and nothing wrong ever runs.
MemoryIndex.java:144 opens "Example Usage"; the program is :147-158 inside <pre><code> (:146, :159):
Analyzer analyzer = new SimpleAnalyzer(version); // MemoryIndex.java:147
MemoryIndex index = new MemoryIndex();
index.addField("content", "Readings about Salmons and other select Alaska fishing Manuals", analyzer);
index.addField("author", "Tales of James", analyzer);
QueryParser parser = new QueryParser(version, "content", analyzer); // MemoryIndex.java:151
float score = index.search(parser.parse("+author:james +salmon~ +fish* manual~"));
if (score > 0.0f) {
System.out.println("it's a match");
} else {
System.out.println("no match found");
}
System.out.println("indexData=" + index.toString());SimpleAnalyzer.java:32:public SimpleAnalyzer() {}is the only constructor.QueryParser.java:91(classic):public QueryParser(String f, Analyzer a); the other two constructors are protected and take one argument (QueryParser(CharStream):921,QueryParser(QueryParserTokenManager):943).- The two errors are about the number of arguments, so with the Lucene imports no declaration of
versionmakes the calls compile. - Nothing in the build checks it: code inside javadoc
<pre>blocks is not compiled, and no{@snippet}is used anywhere underlucene/.
- 2012-09-12: Robert Muir's "code snippet improvements: fix out of date api usage and add syntax highlighting" (
647b5091697trunk,d8d5bf5e07dbranch_4x) wrote both calls in their current form. They were valid; first release 4.0.0. - 2014-08-08: LUCENE-5859 (
9938a39a872, Ryan Ernst, "Remove Version from Analyzer constructors") removedSimpleAnalyzer(Version)andQueryParser(Version, String, Analyzer). In the memory module it changed onlyMemoryIndexTest.java(new QueryParser(TEST_VERSION_CURRENT, "foo", analyzer)becamenew QueryParser("foo", analyzer)), notMemoryIndex.java. - On branch_4x (
cb9beac7079, 4.10.0) the two constructors were only deprecated, so 4.10.x still compiles the example. The branch_5x backport55594bad9b0(LUCENE-5944, 2014-09-18) carried the removal into 5.0.0. - Later commits (2014-2015 doclint fixes, LUCENE-9570 reformatting in 2021, #15573 in 2026) changed only the markup around the block.
Exposure and likelihood113 words
- Who. Readers of the
MemoryIndexclass javadoc, the class's only end-to-end usage example.MemoryIndexis public and not marked@lucene.experimental; the highlighter (WeightedSpanTermExtractor,MemoryIndexOffsetStrategy) and the monitor (DocumentBatch) build on it. Users do quote this example: a 2016 java-user thread copies itsaddFieldlines. - What they get. Two javac errors, on every release from 5.0.0 to 10.6.0 and on main.
- What they do not get. Any runtime effect: no wrong result, no exception at run time. javac names the valid constructors (
SimpleAnalyzer(),QueryParser(String, Analyzer)), so the fix is quick once seen. - Priority. Low; likelihood "plausible" (anyone who copies the example hits it, every time).
One JUnit class, one test, no randomness. It compiles the 12 example lines verbatim with the JDK's in-process compiler; the test wraps them in the five imports, a class and a method example(Version version) throws Exception (the throws because parse declares ParseException). Put it in the monitor module's tests, which have memory, analysis-common and queryparser, and run it with gradle.
/*
* 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.monitor;
import java.io.File;
import java.net.URI;
import java.util.List;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import org.apache.lucene.tests.util.LuceneTestCase;
public class TestMemoryIndexJavadocExample extends LuceneTestCase {
// Expected: the class-javadoc example compiles; actual: no SimpleAnalyzer(Version) /
// QueryParser(Version, String, Analyzer).
public void testClassJavadocExampleCompiles() throws Exception {
String source =
"""
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.index.memory.MemoryIndex;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.util.Version;
class Example {
void example(Version version) throws Exception {
Analyzer analyzer = new SimpleAnalyzer(version);
MemoryIndex index = new MemoryIndex();
index.addField("content", "Readings about Salmons and other select Alaska fishing Manuals", analyzer);
index.addField("author", "Tales of James", analyzer);
QueryParser parser = new QueryParser(version, "content", analyzer);
float score = index.search(parser.parse("+author:james +salmon~ +fish* manual~"));
if (score > 0.0f) {
System.out.println("it's a match");
} else {
System.out.println("no match found");
}
System.out.println("indexData=" + index.toString());
}
}
""";
JavaFileObject unit =
new SimpleJavaFileObject(URI.create("string:///Example.java"), JavaFileObject.Kind.SOURCE) {
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
};
// Lucene modules sit on the module path under gradle and on the class path elsewhere: use both.
String classPath = System.getProperty("java.class.path");
String modulePath = System.getProperty("jdk.module.path");
if (modulePath != null) {
classPath = classPath + File.pathSeparator + modulePath;
}
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
List<String> options =
List.of("-classpath", classPath, "-d", createTempDir().toString(), "-proc:none");
boolean compiled =
ToolProvider.getSystemJavaCompiler()
.getTask(null, null, diagnostics, options, null, List.of(unit))
.call();
assertTrue(diagnostics.getDiagnostics().toString(), compiled);
}
}
./gradlew :lucene:monitor:test --tests org.apache.lucene.monitor.TestMemoryIndexJavadocExample -Ptests.seed=DEADBEEF
- Expected
- With the imports and a declared
version, the 12-line example compiles and, when run, prints "it's a match" (what a reader expects of an "Example Usage" block; Lucene does not compile javadoc code). - Observed
- javac:
SimpleAnalyzer"cannot be applied to given types" and "no suitable constructor found for QueryParser(Version,String,Analyzer)", with assertions on and off.
More files, environment, full output352 words
The test passes the example as a string to javax.tools and asserts that it compiles; on failure the message is javac's own diagnostics. The 12 lines are MemoryIndex.java:147-158 with > decoded; a script checked them against the javadoc line for line. Single thread, public API only. The test shows that the two calls fail with the intended Lucene imports and this ordinary wrapper; it does not test the bare fragment, which needs some such wrapper on every version, 4.10.4 included.
It sits in lucene/monitor because the memory module's own tests have no analysis-common (for SimpleAnalyzer). The javac class path includes the module path, which gradle uses for Lucene's modules. The same file also fails against the 10.6.0, 10.5.2 and 9.12.3 release jars.
Regression test (optional): this same test with the two fixed lines. It guards the documented calls; it cannot notice a later edit of the javadoc itself, since Lucene does not compile javadoc code.
| lucene | main 645d4fe14a20 (11.0.0-SNAPSHOT); 10.6.0, 10.5.2 and 9.12.3 fail the same way |
|---|---|
| jdk | OpenJDK 25.0.3 |
| os | Linux aarch64 (the result does not depend on the platform) |
cp $REPRO/TestMemoryIndexJavadocExample.java $LUCENE/lucene/monitor/src/test/org/apache/lucene/monitor/
cd $LUCENE
./gradlew :lucene:monitor:test --tests org.apache.lucene.monitor.TestMemoryIndexJavadocExample -Ptests.seed=DEADBEEF
# assertions off: add -Ptests.asserts=false (same failure)
# gradle, main 645d4fe14a20, seed DEADBEEF, assertions on (off: the same two errors)
TestMemoryIndexJavadocExample > testClassJavadocExampleCompiles FAILED
java.lang.AssertionError: [/Example.java:8: error: constructor SimpleAnalyzer in class org.apache.lucene.analysis.core.SimpleAnalyzer cannot be applied to given types;
Analyzer analyzer = new SimpleAnalyzer(version);
^
required: no arguments
found: org.apache.lucene.util.Version
reason: actual and formal argument lists differ in length, /Example.java:12: error: no suitable constructor found for QueryParser(org.apache.lucene.util.Version,java.lang.String,org.apache.lucene.analysis.Analyzer)
QueryParser parser = new QueryParser(version, "content", analyzer);
^
constructor org.apache.lucene.queryparser.classic.QueryParser.QueryParser(java.lang.String,org.apache.lucene.analysis.Analyzer) is not applicable
(actual and formal argument lists differ in length)
constructor org.apache.lucene.queryparser.classic.QueryParser.QueryParser(org.apache.lucene.queryparser.charstream.CharStream) is not applicable
(actual and formal argument lists differ in length)
constructor org.apache.lucene.queryparser.classic.QueryParser.QueryParser(org.apache.lucene.queryparser.classic.QueryParserTokenManager) is not applicable
(actual and formal argument lists differ in length)]
at __randomizedtesting.SeedInfo.seed([DEADBEEF:9A7EBD6A0F12FB11]:0)
1 test completed, 1 failed
# Example.java:8 and :12 are lines 1 and 5 of the block (MemoryIndex.java:147 and :151)
# with the fix and the fixed text in the test: BUILD SUCCESSFUL, 1 test (assertions on and off)- The text comes from a 2012 commit titled "fix out of date api usage": it is meant to track the API, and it compiled on 4.0.0-4.10.4.
- LUCENE-5859 removed the constructors and updated the module's test, not this file; its discussion never mentions the example.
- Upstream fixes javadoc examples that do not work (#12666, fixed by #12693; LUCENE-9046).
The full argument165 words
- Meant to track the API.
647b5091697/d8d5bf5e07d(Robert Muir, 2012-09-12), "code snippet improvements: fix out of date api usage and add syntax highlighting", wrote today's text. 4.10.4 compiles it. - An oversight, not a decision.
9938a39a872(LUCENE-5859) touchedMemoryIndexTest.javabut notMemoryIndex.java; the 55 comments of #6921 never mention MemoryIndex; MIGRATE.md and CHANGES.txt say nothing about keeping the example. - Precedent. #12666 (the
Analyzerclass-doc example "does not work") was closed by #12693, "chore: update the Javadoc example in Analyzer" (2023); CHANGES.txt: "LUCENE-9046: Fix wrong example in Javadoc of TermInSetQuery". - Not a placeholder.
versionis undeclared, which a reader can fill in; but with the Lucene imports no declaration ofversionfixes a call to a constructor that does not exist. - What a reader can expect. Lucene does not compile javadoc code, so nothing guarantees that this block compiles. The claim is what a reader reasonably expects of an "Example Usage" block: that, with the imports added and
versiondeclared, it calls API that exists.
The devil's-advocate check139 words
The case for "intended": the block is an uncompiled illustrative fragment (no imports, version never declared, no snippet tooling in the build) inside a class javadoc full of 2005-2006 prose (the Nux XQuery example, dead today.java.net links); the error is loud and names the right constructors; and a maintainer edited this exact block in January 2026 (#15573) without touching the calls.
Why it fails: #15573 ("Replace prettyprint with code tag for prism") changed 252 files mechanically, as the 2014-2015 doclint and 2021 reformatting commits also changed only the markup. With the Lucene imports no declaration of version makes the calls compile: they name API that does not exist. Every reviewer, including two from another model family (OpenAI GPT-5.6), and the adjudication rejected the argument. What remains true is that the impact is small, which is why it is Low.
Recommended Drop the two Version arguments (validated)
Javadoc only: change line 1 of the example to new SimpleAnalyzer() and line 5 to new QueryParser("content", analyzer). Validated with gradle: the example then compiles, and the memory module's 51 tests and its javadoc build pass.
All options and trade-offs3 options ยท 415 words
One fix was validated with gradle in a scratch worktree of 645d4fe14a20; the alternatives were not run.
Exactly the change LUCENE-5859 made to the memory module's test. The example then uses the current constructors and no longer needs the undeclared version at all. 1 file, +2/-2, javadoc only.
--- a/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
+++ b/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
@@ -144,11 +144,11 @@
* <p><b>Example Usage</b> <br>
*
* <pre><code class="language-java">
- * Analyzer analyzer = new SimpleAnalyzer(version);
+ * Analyzer analyzer = new SimpleAnalyzer();
* MemoryIndex index = new MemoryIndex();
* index.addField("content", "Readings about Salmons and other select Alaska fishing Manuals", analyzer);
* index.addField("author", "Tales of James", analyzer);
- * QueryParser parser = new QueryParser(version, "content", analyzer);
+ * QueryParser parser = new QueryParser("content", analyzer);
* float score = index.search(parser.parse("+author:james +salmon~ +fish* manual~"));
* if (score > 0.0f) {
* System.out.println("it's a match");Trade-offs
- No behaviour, API or test change; trivially reviewable.
- Leaves the rest of the 2005-2006 prose (dead links, the XQuery block, JDK 1.5 profiling advice) alone.
What the checks validated
- Scratch worktree of
645d4fe14a20, gradle--offline, OpenJDK 25.0.3, seed DEADBEEF; the test in the monitor module's tests. - Stock: the one-test repro fails with assertions on and off (both javac errors).
- With the diff: a script confirmed the patched javadoc block equals the fixed text line for line; the test with that text passes with assertions on and off.
:lucene:memory:test, the whole module: 51 tests (TestMemoryIndex30,TestMemoryIndexAgainstDirectory16,TestSlicedIntBlockPool5), 0 failures, 0 skipped.:lucene:memory:renderJavadoc,checkGoogleJavaFormatandecjLintMainpass; with the test file in place,:lucene:monitor:checkGoogleJavaFormat,ecjLintTestandforbiddenApisTestpass.- Earlier runs: the corrected example runs and prints "it's a match" (score 1.3487055) on main with
-eaand-daand on 10.5.2; the cross-model reviewer ran 46 existing MemoryIndex tests against the patched source, all passing. - Not run: the whole
:lucene:monitor:testor./gradlew check.
Add the five import lines so the block can be pasted as is. More text in a class javadoc, and other Lucene examples omit imports too; not needed to fix the defect.
Trade-offs
Longer example; same compile check as the recommended option.
What the checks validated
Not run.
Move examples to {@snippet} with compiled source files, or compile <pre> blocks in a build check. The only thing that would stop this class of drift.
Trade-offs
A build-tooling change far beyond a two-line docs fix; out of scope here.
What the checks validated
Not run.
No formal method. A pass compiled the code examples in the javadocs of the memory, monitor, suggest, facet and join modules against the current jars, and this one failed. A scan of 158 builds' jars dated the two constructors; verifiers, reviewers from another model family (OpenAI GPT-5.6) and an adjudication confirmed it.
The method in full95 words
- Lead. A first pass over javadoc examples compiled the block against the stock main jars and got both constructor errors.
- Hunt. The finder re-ran the lead, extracted the block mechanically from the source, and checked with a
java.lang.classfilescan in which of 158 builds (every cached release 1.9.1-10.5.2, the 10.6.0 release candidate and main) the example's API members exist; the boundaries were cross-checked by compiling each release's own javadoc text with javac. It then wrote the one-test repro. - Tier. Non-formal: compiling documentation code and scanning jars for API members, not a check against exact semantics.
No prior report: GitHub issues, PRs and commits (with the migrated JIRA archive), four mailing lists, downstream repositories, Stack Exchange and the web were searched; none of the seven open PRs that touch MemoryIndex.java edits the example.
Searches5 searches
Closest hits, none this bug: #6586 (LUCENE-5523, 2014, closed Cannot Reproduce) quotes the example as the repro of a TokenStream-contract report on 4.7, when it still compiled; #6921 (LUCENE-5859) and #7006 (LUCENE-5944) made it stale without mentioning it; #5862, #10610 and #15573 edited only the markup around it; #8777 fixed an HTML entity above it; #16821 (open) is the same kind of defect in the highlight package docs; #15225, #14257, #4624 and #9527 are generic javadoc discussions; a 2016 java-user thread quotes the example's addField lines, not about compiling. Tracking issue #16937 does not name it.
| Where | When | How | Found |
|---|---|---|---|
| Scripted searches | 2026-10-29 | 16 GitHub issue/PR, 3 commit, 2 downstream, 20 mailing-list, 4 JIRA-archive and 6 web queries, with exact example phrases ("Readings about Salmons", SimpleAnalyzer(version), salmon~) and LUCENE-5859 | 1,098 distinct hits; the 3 high-overlap hits are all from before 5.0 |
| GitHub, manual | 2026-10-29 | 35 manual searches: 26 on apache/lucene (exact example phrases, API and issue names, author listings, and every issue/PR created or updated since 2026-10-27), 3 on downstream repositories, 6 on the old lucene-solr repository and GitHub-wide | no report |
| Open PRs | 2026-10-29 | changed files of all 415 open apache/lucene PRs; patches of the seven that touch MemoryIndex.java (#16847, #14716, #14475, #13948, #13525, #13342, #486) | none edits the example lines |
| Mailing lists, JIRA archive, Stack Exchange, web | 2026-10-29 | 28 lists.apache.org queries (java-user@, dev@, issues@, general@), 5 JQL queries, 3 Stack Overflow threads, 7 web searches | a 2016 java-user thread quoting the addField lines; nothing about compiling |
| History and upstream main | 2026-11-01 | git log -S / -L on the block in the full-history clone; upstream main f815e679bf6c | both calls unchanged upstream; no commit since 645d4fe14a20 touched the file |
Stale since 5.0.0: LUCENE-5859 (9938a39a872, 2014-08-08; released through the branch_5x backport 55594bad9b0) removed both constructors. 4.10.4 compiles the example; every release from 5.0.0 to 10.6.0 and main fail.
Versions tested7 rows
- Example written by
647b5091697/d8d5bf5e07d(2012-09-12, first released in 4.0.0);git blameon main still points there for both lines. - Introduced by
9938a39a872(LUCENE-5859, Ryan Ernst, 2014-08-08, trunk; first released in 6.0.0). 5.0.0 got the removal through the branch_5x backport55594bad9b0(LUCENE-5944, Robert Muir, 2014-09-18), so 5.0.0 is the first affected release. On branch_4x,cb9beac7079(4.10.0) only deprecated both constructors. - Same text everywhere: after stripping markup the example code is identical in all 121 release tags 4.0.0-10.5.2 of the history clone and on main; a bytecode scan of 158 builds finds both constructors in 4.0.0-4.10.4 and in no build from 5.0.0 to main.
- Not fixed upstream: upstream main
f815e679bf6c(2026-11-01) and branch_11x still have both calls at lines 147 and 151; branch_10_6 and the 10.6.0 tag at 115 and 119. Before 4.0.0 the example had an older, different form; not claimed.
| Version or commit | Verdict | Result |
|---|---|---|
main 645d4fe14a20; upstream main f815e679bf6c | affected | repro fails with -ea and -da (standalone and gradle); upstream read: same two lines |
| 10.6.0 | affected | fails 1/1 (release jars); the finder's earlier run used jars built at the same commit 4ae946e5a9b, labelled 10.6.0-SNAPSHOT: also fails |
| 10.5.2, 9.12.3 | affected | fail 1/1 |
| 5.0.0, 6.0.0, 8.11.4 | affected | fail with the same two errors (port that only changes the LuceneTestCase import) |
| 5.0.0 to 10.5.2 (all tags) | affected | read: same example text; both constructors absent from every build |
| 4.10.4 | not affected | the verbatim example compiles (constructors deprecated, not removed) |
| 4.0.0 to 4.10.3 | not affected | read: both constructors present; 4.0.0's text compiles with javac |
Seven independent looks agree it is real and documentation-only: the finder, verifiers, reviewers from another model family (OpenAI GPT-5.6), the adjudication, and a credibility audit. This doc's brief re-ran the repro with gradle and validated the fix.
Checks and verdicts200 words
Each check ran separately; the intended-lens cross-model review could not run code, and a separate run re-ran the repro.
| Check | Verdict | What it found |
|---|---|---|
| Finder | reproduced (doc) | Repro fails on main (-ea, -da), the 10.6.0 release candidate, 10.5.2 and 9.12.3; fix check passes. |
| Refute lens (OpenAI GPT-5.6) | real, high | Own tests fail on main ea57360912ed (same javadoc text); with the fix the block compiles, runs and prints "it's a match"; 46 existing MemoryIndex tests pass. |
| Independent reproducer | real | Own test, run with Version.LATEST: fails on main (-ea, -da), 10.5.2, 9.12.3; control without the two arguments prints "it's a match". |
| Intended lens (OpenAI GPT-5.6) | real, medium (reading only) | Could not execute; a separate run re-ran the repro on main (fails). |
| Devil's advocate | real, Low | Argued "illustrative fragment" and rejected it; runs on main and 10.5.2 fail. |
| Adjudication | confirmed, high | Re-ran the repro on main (fails); documentation defect, severity low. |
| Credibility audit | confirmed, Low | Re-runs on main fail; minor, not noise (removed-API call in the only example). |
| This doc's brief | real; fix validated | Gradle before and after in a scratch worktree; standalone on main, 10.6.0, 10.5.2, 9.12.3. |
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 358 KB
Finding record, Lucene and upstream sources, repro files and diagram notes1,207 words
- Registry title
- MemoryIndex's class javadoc example calls new SimpleAnalyzer(version) and new QueryParser(version, "content", analyzer), constructors removed in 5.0.0 (LUCENE-5859), so the example does not compile on any release since 5.0.0 (documentation defect)
- Area
- memory / MemoryIndex (class javadoc example)
- Priority
- Low, rank 1248: The only end-to-end example for the widely used, non-experimental MemoryIndex has failed to compile since 5.0.0 with no runtime effect.
- Impact class
- minor
- Impact note
- Documentation only, with no runtime effect: a developer who starts from MemoryIndex's only end-to-end usage example (the class javadoc 'Example Usage') and copies it gets two compile errors on every release since 5.0.0, whatever they declare version as; dropping the two Version arguments fixes it, and no configuration, scale or special input is involved.
- Summary
- The MemoryIndex class javadoc shows an 'Example Usage' program that adds two fields to a MemoryIndex, parses '+author:james +salmon~ +fish* manual~' and prints "it's a match". Its first and fifth lines call new SimpleAnalyzer(version) and new QueryParser(version, "content", analyzer), but both Version-taking constructors were removed in 5.0.0 (LUCENE-5859), so the example has not compiled on any release since then, whatever type version is given. With new SimpleAnalyzer() and new QueryParser("content", analyzer) the same example compiles and prints "it's a match" on main and 10.5.2, so only the javadoc is wrong.
- Introduced
- 9938a39a872 (trunk, svn r1616901; LUCENE-5859 'Remove Version from Analyzer constructors', migrated as #6921, by Ryan Ernst (rjernst), author date = commit date 2014-08-08): it removed SimpleAnalyzer(Version) (leaving SimpleAnalyzer()) and the classic QueryParser(Version, String, Analyzer) (leaving QueryParser(String, Analyzer)) and updated MemoryIndexTest.java, but not the MemoryIndex.java class javadoc example. The released 5.x line got the same removal through the branch_5x bulk backport 55594bad9b0 (LUCENE-5944, Robert Muir, 2014-09-18, svn r1626055); 9938a39a872 itself is first released in 6.0.0. On branch_4x, cb9beac7079 (LUCENE-5859, Ryan Ernst, 2014-08-21, first released in 4.10.0) only deprecated both constructors, so 4.10.x still compiles the example. The two calls were written by 647b5091697 (trunk) / d8d5bf5e07d (branch_4x) ('code snippet improvements: fix out of date api usage and add syntax highlighting', Robert Muir, 2012-09-12, first released in 4.0.0) and were valid then [read: git log, show, blame and tag --contains in the full-history clone and a Lucene clone; exec: release runs, see affected_versions] (2014-08-08 (9938a39a872, trunk, author date = commit date); released through the branch_5x backport 55594bad9b0 of 2014-09-18)
- First affected version
- 5.0.0 [exec] (the verbatim example compiles on 4.10.4 [exec], where both constructors still exist as deprecated, and fails on 5.0.0 with identical example text)
- Affected versions
- every release from 5.0.0 to 10.6.0 (RC1 4ae946e5a9b), branch_10x 657014b3c579, branch_11x f85446cb1af1 and main 645d4fe14a20; not fixed upstream (recheck 2026-10-29: both calls are still at lines 147 and 151 on main and branch_11x and at lines 115 and 119 on branch_10x and branch_10_6; the latest commit touching the file on main, bfe5c847d3c4 (#16383, author date 2026-07-27), does not change them). [exec: 4.10.4 compiles; 5.0.0, 6.0.0, 8.11.4, 9.12.3, 10.5.2, the 10.6.0 RC1 jars and main (-ea and -da) fail with the same two javac errors; the pre-9.0 runs use an import-only port of the test (LuceneTestCase package) and the junitcore runner] [read: a bytecode scan of 158 builds (every cached release 1.9.1-10.5.2, the 10.6.0 RC1 and main) finds SimpleAnalyzer(Version) and QueryParser(Version, String, Analyzer) in 4.0.0-4.10.4 and in no build from 5.0.0 to main; the example code (markup stripped) is identical in all 121 release tags 4.0.0-10.5.2 of the history clone (the 8.9.0-8.11.x tags are not in it) and on main]. branch_10x and branch_11x: text only (that jar set has no memory or queryparser jar). Before 4.0.0 the example had an older, different form (not claimed). Not new in 10.6. 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 agreed, 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; the finder's, the independent reproduction's, the intended-behaviour check's and the adjudication's searches agree): 125 queries, among them scripted searches over GitHub issues, PRs and commits, downstream repositories, the dev@, java-user@, issues@ and general@ lists, the JIRA archive and the web, 35 manual GitHub search phrasings (apache/lucene, the old lucene-solr repository, three downstream search-engine repositories and GitHub-wide), the changed files of all 415 open apache/lucene PRs and the patches of the seven that touch MemoryIndex.java (#16847, #14716, #14475, #13948, #13525, #13342, #486; none edits the example lines), 28 direct lists.apache.org queries, 5 JIRA-archive queries, Stack Exchange, and git log -S / -L on the example in the full history. Read but not the same bug: #6586 (LUCENE-5523, 2014, closed Cannot Reproduce) quotes the example as the reproduction of a TokenStream-contract report on 4.7, when it still compiled; #6921 (LUCENE-5859) and #7006 (LUCENE-5944), the changes that made it stale, never mention MemoryIndex's example; #5862 (LUCENE-4797), #10610 (LUCENE-9570) and #15573 later edited the markup around the example and left the code; #8777 (LUCENE-7726) fixed an HTML entity above it; #16821 (open, by hidingmyname, 2026-10-12) is the same kind of defect in the highlight package docs; #15225, #14257, #4624 and #9527 are generic javadoc or snippet discussions that name no MemoryIndex example; a 2016 java-user thread quotes the example's addField lines without mentioning the constructors. Recheck: upstream main still 645d4fe14a20; both calls still present on main, branch_11x, branch_10x and branch_10_6; none of the 63 issues and PRs updated since 2026-10-27 (newest #16940) names MemoryIndex, SimpleAnalyzer(version) or QueryParser(version, and none of their 25 PRs changes MemoryIndex.java. Tracking issue #16937 does not name it.
- Lucene commit tested
- main
645d4fe14a20(2026-10-28): the one-test repro fails with assertions on and off (standalone, and gradle with the file in the monitor module's tests); it fails against the 10.6.0, 10.5.2 and 9.12.3 release jars; the version-history runs ran 4.10.4 (compiles) and 5.0.0, 6.0.0 and 8.11.4 (the same two errors); the fix was validated with gradle in a scratch worktree of645d4fe14a20. Upstream mainf815e679bf6c(2026-11-01) was read, not run: both calls are unchanged and no commit since645d4fe14a20touched the file.
- Finding record
lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java:144-159 (class javadoc 'Example Usage', the stale calls at :147 and :151; the class carries no @lucene.experimental tag); lucene/analysis/common/src/java/org/apache/lucene/analysis/core/SimpleAnalyzer.java:32 (the only constructor, SimpleAnalyzer()); lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParser.java:91 (QueryParser(String f, Analyzer a))
- The finding in 30 seconds
lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java (lines 144-159, 147, 151, 201)lucene/analysis/common/src/java/org/apache/lucene/analysis/core/SimpleAnalyzer.java:32lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParser.java:91, :921, :943
- Who is affected
lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java:201 (public class, no class-level @lucene.experimental)lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java (new MemoryIndex)lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MemoryIndexOffsetStrategy.java (new MemoryIndex)lucene/monitor/src/java/org/apache/lucene/monitor/DocumentBatch.java (new MemoryIndex)
- Minimal repro
lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java:129 (parse(String) throws ParseException)
- Why it looks unintended
lucene/CHANGES.txt:6147 (LUCENE-9046)
- History
a Lucene clone: git tag --contains 55594bad9b0 (first release tag 5.0.0), 9938a39a872 (first release tag 6.0.0); releases/lucene-solr/5.0.0 MemoryIndex.java:129, :133; releases/lucene/10.6.0 MemoryIndex.java:115, :119; origin/branch_11x :147, :151; origin/branch_10_6 :115, :119
- TestMemoryIndexJavadocExample.java (one test, monitor module tests):
repro/LFV-1032/TestMemoryIndexJavadocExample.java(79 lines)
Made in parallel with this doc from the mechanism in the brief; the PNG is the summary frame.
assets/LFV-1032/bug.png(358 KB)
