All findings · Lucene finding · LFV-972 · lucene104-file-extensions-table-stale

The default codec's file-extension table is stale: seven extensions it writes are missing, and the vector row lists .veq instead of .vemf

The "Summary of File Extensions" table in the File Formats overview leaves out 7 of the 21 extensions that one ordinary document produces with the default codec, and its vector row lists .veq, which the default vector format never writes. Lucene handles every file correctly; only the documentation is wrong.

Summary

Priority
Low, rank 1281The stale extension table in the default codec overview leaves out common files, but the per-format javadocs list nearly all of them and it is a missing-name list, not a wrong byte grammar.
Impact
minor
Since
8.5.0 (LUCENE-9147, 2020); the vector row incomplete since 9.0.0, in its current wrong form since 9.9.0introduced 2020-02-05 · about 6 years
Affected
8.5.0 to 10.6.0 and main
Status
documented
Found by
semi-formal: written files compared with the table over 91 generated indexes

AI-assisted page: this finding was first signalled by a semi-formal check (an exact check of the real jar, or a modelling hypothesis that a tool then witnessed) 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 table that maps file extensions to formats in the File Formats overview has not kept up with the default codec since 8.5.0.

Background: index files and the extension table

  1. A Lucene segment is a set of files that share a name and differ by extension; each format of the codec writes its own files, for example .tim for the terms dictionary. Small segments are packed into one compound .cfs file; by default, merged segments above 64 MB stay separate files.
  2. The default codec's package documentation, the File Formats overview, has a "Summary of File Extensions" table: one row per kind of file, its extensions, a short description and a link to the format page with the details.
Diagram of the bug: the 21 extensions that one document with a stored field with term vectors, a numeric doc-values field and a 2-dimensional vector writes with the default codec, non-compound, checked against the Summary of File Extensions table. Fourteen match a row; seven have no row: .fdm, .tvm, .tmd, .psm, .dvs, .dvp and .vemf. The vector row reads .vec, .vem, .veq, vex, while the default vector format wrote .vec, .vem, .vemf and .vex: .veq comes only from the optional quantized formats and vex lacks its dot. Lucene itself reads and writes every file correctly; only the documentation is wrong.
The files one ordinary document writes, checked against the table's rows: seven extensions have no row, and the vector row lists .veq and an undotted vex where the default format writes .vemf and .vex. Select the still to open it at full size. Generated with AI, checked against the code.

The finding, step by step

  1. You index one document with a stored field with term vectors, a numeric doc-values field and a 2-dimensional vector, with the default codec and no compound file. The directory gets 21 segment files with 21 different extensions.
  2. You look each extension up in the File Formats overview's "Summary of File Extensions" table, which "summarizes the names and extensions of the files". It lists 25 extensions, including the metadata files .nvm, .dvm, .kdm and .vem, so you expect all 21 there.
  3. 7 are missing: .fdm, .tvm, .tmd and .psm (stored-fields, term-vectors, terms and postings metadata), .dvs and .dvp (doc-values skip index and presence data) and .vemf (vector metadata).
  4. The vector row says .vec, .vem, .veq, vex; the default vector format wrote .vec, .vem, .vemf and .vex. .veq comes only from the optional quantized formats, and vex lacks its dot. The postings format's own file list also omits .tmd and .psm.
  5. Why: since 8.5.0 (2020), six format changes each added a file and documented it at most on its own format page, never in this table.

Who is affected

People and tools that learn a segment's files from the overview: someone sizing an index by file type, a backup or copy tool that picks files by extension, a format port. Default codec, ordinary documents; the files show for non-compound segments (by default, merged segments above 64 MB). Lucene and its searches are unaffected.

Mechanism, terms and numbers582 words

The default codec's package documentation (codecs/lucene104/package-info.java, the File Formats overview) says it "defines the index file formats used in this version of Lucene" (:50), and its "Summary of File Extensions" table "summarizes the names and extensions of the files in Lucene" (:211, table :213-319). The table lists the metadata files of norms, doc values, points and vectors (.nvm, .dvm, .kdm, .vem) but not seven extensions the default codec writes for ordinary documents: .fdm, .tvm, .tmd, .psm, .dvs, .dvp and .vemf.

Its vector row (:312-318) links the default Lucene99HnswVectorsFormat and reads .vec, .vem, .veq, vex: that format writes .vec, .vemf, .vem and .vex, .veq comes only from the optional scalar-quantized formats, and vex has no dot. The default postings format's "Files and detailed format" list (Lucene104PostingsFormat.java:81-89) names .tim, .tip, .doc, .pos and .pay but not the .tmd and .psm files the same format writes.

Lucene writes, reads, merges and checks all these files correctly; nothing reads the table at runtime. The table matched the codec through 8.4.1. None of the six format changes since 8.5.0 (2020) that added the missing files put them in the table: five touched no package-info.java, and #13585 copied the whole table into its new lucene912 package without a .psm row. The vector row's current text was written by #12582 (9.9.0), when the HNSW format could still write .veq; from 9.0.0 through 9.8.0 the row read .vec, .vem and lacked .vex. Documentation only; the fix is javadoc text.

One document, non-compound, default codec (main 645d4fe14a20)

A stored StringField with term vectors, a NumericDocValuesField and a 2-dimensional KnnFloatVectorField give 22 files: segments_1 and 21 segment files.

writtenin the table?written by (constant, file:line)on its own format page
.si, .fnm, .fdt, .fdx, .tvd, .tvx, .tim, .tip, .doc, .dvd, .dvm, .vec, .vemyes
.vexas vex, without the dotLucene99HnswVectorsFormat.java:90
.fdmnoLucene90CompressingStoredFieldsWriter.java:67, created :131-132Lucene90StoredFieldsFormat.java:92
.tvmnoLucene90CompressingTermVectorsWriter.java:69, created :259-260Lucene90TermVectorsFormat.java:54
.tmdno (nor in the postings list)Lucene103BlockTreeTermsReader.java:84, created Lucene103BlockTreeTermsWriter.java:321-324Lucene103BlockTreeTermsWriter.java:91, :147
.psmno (nor in the postings list)Lucene104PostingsFormat.java:325, created Lucene104PostingsWriter.java:153only the constant's one-line javadoc
.dvs, .dvpnoLucene90DocValuesFormat.java:195, :197; both created for every segment with doc values (Lucene90DocValuesConsumer.java:110, :120)Lucene90DocValuesFormat.java:135-136
.vemfnoLucene99FlatVectorsFormat.java:81; the HNSW format always uses this flat format (Lucene99HnswVectorsFormat.java:155-156)Lucene99FlatVectorsFormat.java:48

With compound files the directory holds only _0.cfe, _0.cfs, _0.si and segments_1, all listed.

The vector row (package-info.java:312-318)

It links Lucene99HnswVectorsFormat, the default (Lucene104Codec.java:123), with the cell .vec, .vem, .veq, vex and the text ".vem the vector metadata, .veq the quantized vector data, and .vex the hnsw graph data". In lucene/core, .veq (with .vemq) is defined only by the optional Lucene104ScalarQuantizedVectorsFormat (:107-108); the read-only backward-codecs Lucene99ScalarQuantizedVectorsFormat (:53-54) defines the same two for old indexes. The default format writes .vec and .vemf through its flat format and .vem and .vex itself (:89-90).

The postings list (Lucene104PostingsFormat.java:81-89)

"Files and detailed format:" .tim, .tip, .doc, .pos, .pay. The format also writes .psm and, through its terms dictionary (:410-413), .tmd; .tim and .tip, also terms-dictionary files, are listed.

Exposure and likelihood274 words
  • Who is hit. Anyone who looks an index file up in the File Formats overview, or builds on it: sizing an index by file type, a backup, copy or inspection tool that selects files by extension, a port of the format. Lucene users who only call its APIs are unaffected, and Lucene's own file lists (SegmentInfo.files(), the commit's file names) are correct.
  • Default vs opt-in. The default codec and ordinary documents: .fdm, .tmd and .psm are written for nearly every segment (stored fields and postings), .dvs and .dvp for every segment with doc values, .vemf for every segment with vectors, .tvm with term vectors.
  • When the files are visible. Flushed segments are compound by default (IndexWriterConfig.java:99, DocumentsWriterPerThread.java:643), but a merge writes any segment above 64 MB as separate files (CompoundFormat.java:42, :163-179; the default TieredMergePolicy measures bytes, MergePolicy.java:598-600). So any default index with a merged segment above 64 MB shows them in its directory.
  • Scale. None needed: one document shows 7 of 21 extensions unlisted.
  • What it does not do. No wrong results, no index change, no runtime path. Every missing file except .psm is documented on its own format page, though not every such page is reachable from the table: .tmd's page (Lucene103BlockTreeTermsWriter) is one link away from the table's postings link, and .vemf's page (Lucene99FlatVectorsFormat) cannot be reached from the vector row's link, whose page links only the abstract FlatVectorsFormat (Lucene99HnswVectorsFormat.java:41). The searches found no report of it although it dates from 8.5.0 (2020), which suggests the audience is small. Impact class minor, priority low.

Minimal repro

One JUnit test indexes one document (a stored field with term vectors, a numeric doc-values field, a 2-dimensional vector) with the default codec into a non-compound directory and looks every written extension up in a verbatim copy of the table's 25 extensions. Deterministic, single thread, about 1.7 s; the same with assertions on and off.

TestLucene104ExtensionTable.java (JUnit, one test)66 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.codecs.lucene104;

import java.util.Set;
import java.util.TreeSet;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.KnnFloatVectorField;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.IndexFileNames;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.ByteBuffersDirectory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.tests.util.LuceneTestCase;

public class TestLucene104ExtensionTable extends LuceneTestCase {

  private static final Set<String> SUMMARY_OF_FILE_EXTENSIONS_TABLE =
      Set.of(
          "si", "cfs", "cfe", "fnm", "fdx", "fdt", "tim", "tip", "doc", "pos", "pay", "nvd", "nvm",
          "dvd", "dvm", "tvx", "tvd", "liv", "kdd", "kdi", "kdm", "vec", "vem", "veq", "vex");

  public void testTableListsEveryExtensionTheDefaultCodecWrites() throws Exception {
    FieldType storedWithTermVectors = new FieldType(StringField.TYPE_STORED);
    storedWithTermVectors.setStoreTermVectors(true);
    Document doc = new Document();
    doc.add(new Field("id", "1", storedWithTermVectors));
    doc.add(new NumericDocValuesField("dv", 1));
    doc.add(new KnnFloatVectorField("vector", new float[] {1, 2}));
    Set<String> missing = new TreeSet<>();
    try (Directory dir = new ByteBuffersDirectory()) {
      IndexWriterConfig iwc =
          new IndexWriterConfig().setCodec(new Lucene104Codec()).setUseCompoundFile(false);
      try (IndexWriter w = new IndexWriter(dir, iwc)) {
        w.addDocument(doc);
      }
      for (String file : dir.listAll()) {
        String extension = IndexFileNames.getExtension(file);
        if (file.startsWith(IndexFileNames.SEGMENTS) == false
            && SUMMARY_OF_FILE_EXTENSIONS_TABLE.contains(extension) == false) {
          missing.add(extension);
        }
      }
    }
    // expected: the table lists every written extension; actual: 7 extensions are missing
    assertEquals("written extensions missing from the extensions table", Set.of(), missing);
  }
}
Command
cp TestLucene104ExtensionTable.java $LUCENE/lucene/core/src/test/org/apache/lucene/codecs/lucene104/
cd $LUCENE && ./gradlew :lucene:core:test --tests org.apache.lucene.codecs.lucene104.TestLucene104ExtensionTable -Ptests.seed=DEADBEEF
# assertions off: add -Ptests.asserts=false (same result)
Expected
Every extension the document writes is in the table: the set of missing extensions is empty.
Observed
expected:<[]> but was:<[dvp, dvs, fdm, psm, tmd, tvm, vemf]>, with assertions on and off.

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

More files, environment, full output444 words
  • The test embeds the table, so it checks today's text, not a parse of it. That its 25 extensions equal the table's was checked mechanically at 645d4fe14a20, 10.5.2, 10.6.0 and later main (a control set compares different, so the check is not vacuous).
  • It asserts the missing extensions only. The vector row and the postings list rest on the source lines (see the explanation above) and on the version-aware check, which parses the table and the list from source, indexes 300 documents non-compound and compound, and fails four ways on main (shown in the full output).
  • Even simpler for a reader: put the table (package-info.java:213-319) next to a directory listing of a non-compound segment.
  • Results: fails 1 of 1 on main with assertions on and off (seed DEADBEEF; the test data has no random values, though LuceneTestCase still randomizes things such as locale and time zone), standalone and through gradle; on the 10.4.0, 10.5.2 and 10.6.0 release jars it reports 5, 6 and 7 missing extensions.
  • As a regression test: the same test with the seven extensions added to its set passes on the fixed tree and fails the next time the default codec writes an extension the set lacks. It keeps veq, which fix A moves out of the vector row's extension cell, so its set has 32 extensions and the fixed table 31 (dropping veq would make them equal; not run). Like the repro it checks only that every written extension is in its set, not the vector row, the dots or the postings list.

Environment

lucenemain 645d4fe14a20 (11.0.0-SNAPSHOT); also fails on the 10.4.0, 10.5.2 and 10.6.0 release jars
jdkOpenJDK 25.0.3 (build 25.0.3+9-LTS)
osLinux, aarch64
Command (environment)
cp TestLucene104ExtensionTable.java $LUCENE/lucene/core/src/test/org/apache/lucene/codecs/lucene104/
cd $LUCENE && ./gradlew :lucene:core:test --tests org.apache.lucene.codecs.lucene104.TestLucene104ExtensionTable -Ptests.seed=DEADBEEF
# assertions off: add -Ptests.asserts=false (same result)

Observed output

TestLucene104ExtensionTable > testTableListsEveryExtensionTheDefaultCodecWrites FAILED
    java.lang.AssertionError: written extensions missing from the extensions table expected:<[]> but was:<[dvp, dvs, fdm, psm, tmd, tvm, vemf]>
        at __randomizedtesting.SeedInfo.seed([DEADBEEF:33A5926AE3A763FA]:0)
        at org.junit.Assert.fail(Assert.java:89)
        at org.junit.Assert.failNotEquals(Assert.java:835)
        at org.junit.Assert.assertEquals(Assert.java:120)
        at org.apache.lucene.codecs.lucene104.TestLucene104ExtensionTable.testTableListsEveryExtensionTheDefaultCodecWrites(TestLucene104ExtensionTable.java:64)

# release jars: 10.4.0 [fdm, psm, tmd, tvm, vemf]; 10.5.2 [dvs, fdm, psm, tmd, tvm, vemf]; 10.6.0 [dvp, dvs, fdm, psm, tmd, tvm, vemf]

# version-aware check (parses the table and the postings list from source), main:
FAIL A: written but absent from the table (excluding points files): [dvp, dvs, fdm, psm, tmd, tvm, vemf]
FAIL B: vector row lists [.vec, .vem, .veq, vex] but the default vectors format wrote [vec, vem, vemf, vex]
FAIL C: table extension cells without a leading dot: [vex]
FAIL D: written by Lucene104PostingsFormat but absent from its 'Files and detailed format' list [doc, pay, pos, tim, tip]: [psm, tmd]
failures=4

Why it looks unintended

  • The page "defines the index file formats used in this version"; its table lists norms, doc-values, points and vector metadata files, not these.
  • The vector row is wrong, not short: it credits .veq to a format that never writes it, omits .vemf and writes vex undotted.
  • Upstream fixed the same staleness in this table before (#13801, points row).
The full argument246 words
  • Contract text. package-info.java:50: "This document defines the index file formats used in this version of Lucene"; :211: "The following table summarizes the names and extensions of the files in Lucene". The table was added (LUCENE-1841, #2916, 2009) so readers can look files up by extension.
  • No rule explains the omissions. The table lists the metadata files of norms, doc values, points and vectors (.nvm, .dvm, .kdm, .vem), but not those of stored fields, term vectors, terms, postings and flat vectors.
  • History shows omissions, not decisions. None of the six changes that added the missing files put them in the table: five touched no package-info.java, and #13585, which copied the whole table into its new lucene912 package, gave .psm no row and documented it only in the constant's javadoc. The PR discussions the follow-up read do not mention the table. A history search (git log -G over every package-info.java) found no version of the table that ever had a cell with any of the seven extensions. vex was dotted in 10.2.x and came back undotted from an older copy in 10.3.0.
  • Precedent. #13801 (romseygeek, merged 2024-09-18, "Correct Point file extensions in Codec javadocs") replaced the stale points cell .dii, .dim with .kdd, .kdi, .kdm. Other file-format doc fixes: LUCENE-7532 (#8583), #15625.
  • Tests. No test or build check was found that compares the overview with the files written (searched lucene/*/src/test, build-tools and gradle at 645d4fe14a20).
The devil's-advocate check179 words

Strongest case for "intended" (the refute reviewer, the intended-lens cross-model reviewer and the devil's-advocate verifier; all rated it moderate): the page "attempts to provide a high-level definition" (:54), the table only "summarizes", the details are "provided in their linked pages" (:188), and those pages document the missing files (all but .psm); .veq is a real extension of this version (the optional scalar-quantized formats); and the codec is @lucene.experimental (Lucene104Codec.java:53).

Why it fails: a summary may be short, but not wrong: the vector row states something false about the format it links, vex is a typo, and listing some formats' metadata files but not others is inconsistency, not brevity. @lucene.experimental allows the format to change, not the current one to be described wrongly. The linked pages do not close the gap either: .vemf's page cannot be reached from the vector row's link, .tmd's is one link further on, and .psm has no page. Upstream treated exactly this as a defect in #13801. Every verifier and the adjudication rejected the "intended" reading.

Suggested fix

Recommended A. Update the table and the postings list to the files the default codec writes

Add rows for .fdm, .tvm, .tmd and .psm; add .dvs, .dvp to the doc-values row; make the vector row .vec, .vemf, .vem, .vex, noting that optional quantized formats add .veq and .vemq; list .tmd and .psm in the postings format's files. Javadoc only. Validated: a check that parses the fixed text finds no gap; tests and static checks pass.

All options and trade-offs3 options ยท 977 words

Three ways to resolve it; A was validated. Targets: main and branch_11x, plus branch_10_6 if wanted (branch_10x was decommissioned, #16911). In 10.6.0 package-info.java is the same file and the postings list the same text, so the diff should apply there too (not tried).

Optional extras: the frozen backward-codecs lucene99 and lucene103 package docs carry the same vector row; fixing them is optional, as they describe old codecs.

A. Update the table and the postings list to the files the default codec writes (validated by the checks) (recommended)

Four new rows (.fdm Field Metadata, .tmd Term Metadata, .psm Postings Metadata, .tvm Term Vector Metadata), each linked to its format like its neighbours; the doc-values row becomes .dvd, .dvm, .dvs, .dvp; the vector row becomes .vec, .vemf, .vem, .vex, describes .vemf as the raw vector metadata and .vem as the HNSW graph metadata, and says the optional scalar-quantized formats add .veq and .vemq. In Lucene104PostingsFormat, the "Files and detailed format" list gains .tmd (with a link to Lucene103BlockTreeTermsWriter) and .psm (maximum impact sizes and the end pointers of the .doc, .pos and .pay files, as Lucene104PostingsWriter.java:711-720 writes). Two files, +28/-4 lines.

diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104PostingsFormat.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104PostingsFormat.java
index f2fb84f3a7e..df59b54aa43 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104PostingsFormat.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104PostingsFormat.java
@@ -83,9 +83,12 @@ import org.apache.lucene.util.packed.PackedInts;
  * <ul>
  *   <li><code>.tim</code>: <a href="#Termdictionary">Term Dictionary</a>
  *   <li><code>.tip</code>: <a href="#Termindex">Term Index</a>
+ *   <li><code>.tmd</code>: Term Metadata, see {@link Lucene103BlockTreeTermsWriter}
  *   <li><code>.doc</code>: <a href="#Frequencies">Frequencies and Skip Data</a>
  *   <li><code>.pos</code>: <a href="#Positions">Positions</a>
  *   <li><code>.pay</code>: <a href="#Payloads">Payloads and Offsets</a>
+ *   <li><code>.psm</code>: Postings metadata (maximum impact sizes and the end pointers of the
+ *       .doc, .pos and .pay files)
  * </ul>
  *
  * <a id="Termdictionary"></a>
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene104/package-info.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene104/package-info.java
index ebcf8c1e5e4..1a90a706783 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene104/package-info.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene104/package-info.java
@@ -255,6 +255,11 @@
  * <td>The stored fields for documents</td>
  * </tr>
  * <tr>
+ * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90StoredFieldsFormat Field Metadata}</td>
+ * <td>.fdm</td>
+ * <td>Metadata about the stored fields and their index</td>
+ * </tr>
+ * <tr>
  * <td>{@link org.apache.lucene.codecs.lucene104.Lucene104PostingsFormat Term Dictionary}</td>
  * <td>.tim</td>
  * <td>The term dictionary, stores term info</td>
@@ -265,6 +270,11 @@
  * <td>The index into the Term Dictionary</td>
  * </tr>
  * <tr>
+ * <td>{@link org.apache.lucene.codecs.lucene104.Lucene104PostingsFormat Term Metadata}</td>
+ * <td>.tmd</td>
+ * <td>Per-field term statistics and the location of the Term Index</td>
+ * </tr>
+ * <tr>
  * <td>{@link org.apache.lucene.codecs.lucene104.Lucene104PostingsFormat Frequencies}</td>
  * <td>.doc</td>
  * <td>Contains the list of docs which contain each term along with frequency</td>
@@ -280,13 +290,18 @@
  * <td>Stores additional per-position metadata information such as character offsets and user payloads</td>
  * </tr>
  * <tr>
+ * <td>{@link org.apache.lucene.codecs.lucene104.Lucene104PostingsFormat Postings Metadata}</td>
+ * <td>.psm</td>
+ * <td>Small metadata about how postings are encoded</td>
+ * </tr>
+ * <tr>
  * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90NormsFormat Norms}</td>
  * <td>.nvd, .nvm</td>
  * <td>Encodes length and boost factors for docs and fields</td>
  * </tr>
  * <tr>
  * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat Per-Document Values}</td>
- * <td>.dvd, .dvm</td>
+ * <td>.dvd, .dvm, .dvs, .dvp</td>
  * <td>Encodes additional scoring factors or other per-document information.</td>
  * </tr>
  * <tr>
@@ -295,6 +310,11 @@
  * <td>Stores offset into the document data file</td>
  * </tr>
  * <tr>
+ * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90TermVectorsFormat Term Vector Metadata}</td>
+ * <td>.tvm</td>
+ * <td>Metadata about the term vectors and their index</td>
+ * </tr>
+ * <tr>
  * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90TermVectorsFormat Term Vector Data}</td>
  * <td>.tvd</td>
  * <td>Contains term vector data.</td>
@@ -311,10 +331,11 @@
  * </tr>
  * <tr>
  * <td>{@link org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat Vector values}</td>
- * <td>.vec, .vem, .veq, vex</td>
+ * <td>.vec, .vemf, .vem, .vex</td>
  * <td>Holds indexed vectors; <code>.vec</code> files contain the raw vector data,
- * <code>.vem</code> the vector metadata, <code>.veq</code> the quantized vector data, and <code>.vex</code> the
- * hnsw graph data.</td>
+ * <code>.vemf</code> the raw vector metadata, <code>.vem</code> the hnsw graph metadata, and
+ * <code>.vex</code> the hnsw graph data. The optional scalar-quantized formats add
+ * <code>.veq</code> (quantized vector data) and <code>.vemq</code> (its metadata).</td>
  * </tr>
  * </table>
  *

Trade-offs

  • Covers every gap; the descriptions are short and match the writers. The .psm description is the only one that is new text (no format page describes the file today).
  • The table still has to be kept up to date by hand. A test like the repro, with its set updated, would catch the next gap (optional).
  • For a branch_10_6 backport the same diff should apply (not tried); .dvp exists there (10.6.0).

What the checks validated

Validated in a scratch worktree of 645d4fe14a20 with the diff applied (removed afterwards), seed DEADBEEF, 2026-11-01:

  • The fixed text matches the files. The version-aware check, which parses the table and the postings list straight from the patched source and indexes 300 documents with the default codec (non-compound and compound), reports 0 failures with assertions on and off; on the stock text it reports 4 (missing extensions, vector row, undotted vex, postings list).
  • Suite: ./gradlew :lucene:core:test --tests org.apache.lucene.codecs.lucene104.TestLucene104PostingsFormat --tests org.apache.lucene.codecs.lucene104.TestLucene104ExtensionTableFixed: 35 tests (34 of the suite, 2 of them skipped by the framework, and the repro with the seven extensions added to its set), BUILD SUCCESSFUL with assertions on and off.
  • Static checks and docs: :lucene:core:checkGoogleJavaFormat passes with the diff unchanged; :lucene:core:check -x test (ecjLint, forbiddenApis, google-java-format, the regenerate checksums) and :lucene:core:renderJavadoc pass; the rendered page shows the four new rows and the corrected doc-values and vector rows, and the rendered postings list shows .tmd and .psm.
  • The unchanged repro still fails on the patched tree, as it must: it embeds the old table. Through gradle on stock 645d4fe14a20 it fails with assertions on and off.
  • The full Lucene test suite was not run (javadoc-only change).

B. Fix only the plainly wrong parts

Correct the vector row (.vec, .vemf, .vem, .vex and the .veq note) and the postings list; leave the missing metadata rows.

Trade-offs

Smallest diff, but the table stays incomplete and inconsistent (some formats' metadata files listed, others not), which is the larger part of the defect. Not run.

C. Fix the vector row and say what the table leaves out

Fix the vector row and the postings list, and change :211 to say the table lists the main files of each format and that each linked page lists its metadata files.

Trade-offs

Nothing left to drift for future metadata files, but readers looking up an unknown file by extension still have to search the format pages, which is what the table is for. Not run.

Downstream note

Downstream relevance only for tools that select or copy index files by the table's extensions instead of Lucene's own file lists; Lucene, and products that read indexes through Lucene, are unaffected.

How it was found

Semi-formal: a differential check extracted the table's extension cells and the postings "Files" list from the javadoc source and compared them both ways with the files of 91 generated default-codec indexes. Seven written extensions were never listed and the listed .veq was never written by the default format; on the fixed text a 41-configuration sweep finds nothing.

The method in full206 words
  • Hunt unit, 2026-10-28: the table's extension cells and Lucene104PostingsFormat's "Files and detailed format" list were extracted mechanically from the javadoc source. The extensions written were collected from the real files (top level and inside compound files) of 91 generated indexes: 11 fixed configurations (two of them with a scalar-quantized vectors format) and 80 seeded random feature mixes (stored fields, term vectors, postings with positions, offsets and payloads, norms, all five doc-values types dense and sparse with and without a skip index, points, float, byte and float16 vectors, deletions, soft deletes, doc-values updates, compound files, a file-system directory). The two sets were compared both ways, with assertions on and off.
  • Result: written but not in the table [.dvp, .dvs, .fdm, .psm, .tmd, .tvm, .vemf]; in the table but never written by the default format [.veq]; postings list misses [.psm, .tmd]. On the fixed text the same extraction, run as a separate 41-configuration sweep (the 11 fixed and 30 seeded random), finds nothing missing, extra or undotted (positive control; a sweep, not a proof).
  • Starting lead: a follow-up of an earlier unit that collected the set of extensions the default codec writes. This is a differential check, not model checking or a proof.

Prior reports, history and checks

Prior reports

No prior report in GitHub issues, PRs and commits, the JIRA archive, the mailing lists, downstream projects or the web (searched 2026-10-28, again 2026-11-01). Nearest: #13801, which fixed only the points row of the same table. Not fixed upstream.

Searches2 searches
  • Related, not this bug: #13801 (fixed only the points row; precedent); #16939 / #16941 (a wrong link to the File Formats page from the docs build, fixed 2026-10-29; not the table's content); #16491 (stale block-size comments in the lucene104 reader and writer); #15625 (a different sentence of the postings javadoc); #10744 (a 2021 comment that package javadocs are copied "pretty inconsistently", naming no row); #2916 (where the table came from); the PRs that added each file (none discusses the table).
  • Open PRs: #16480 touches lucene104/package-info.java only to add a History bullet; #16949 (a javadoc-fix series) has no codec file-format item.
  • Not fixed upstream: upstream main f815e679bf6c (2026-11-01) has the same blobs of both files; the latest commits are #15160 (2025-09-10) on package-info.java and #15625 (2026-01-28 UTC; 2026-01-29 in the author's time zone) on Lucene104PostingsFormat.java.
What was searched, when, and what turned up
WhereWhenHowFound
apache/lucene issues, PRs and commits; the JIRA archive; downstream repositories; mailing lists; web2026-10-28scripted prior-report searches (three runs plus the finder's: GitHub, commit, downstream, mailing-list and JIRA-archive queries), 19 more searches on apache/lucene, 18 on downstream repositories, 9 web searches; the changed files of all 414 open apache/lucene PRsno report; nearest #13801 (points row only) and #10744 (a general remark)
apache/lucene and the lists (recheck)2026-11-01scripted prior-report searches (4 runs: 64 GitHub issue/PR, 12 commit, 8 downstream, 80 mailing-list and 16 JIRA-archive queries); 37 manual GitHub searches ("Summary of File Extensions", "Files and detailed format", each extension, Lucene104PostingsFormat, "file formats" stale/outdated, date-bounded); every issue and PR updated since 2026-10-27 (118) and the changed files of the 51 open PRs updated since then; 5 web searchesno report; only #16480 touches the package-info file (a History bullet)

History

Grew one gap per format change since 8.5.0 (2020): .fdm/.tvm 8.5.0, .tmd 8.6.0, the vector row's current wrong form 9.9.0 (it had lacked .vex since 9.0.0), .psm 9.12.0, .dvs 10.5.0, .dvp 10.6.0. 8.4.1 matches its table; every release from 8.5.0 to 10.6.0, and main, does not.

Versions tested6 rows
  • Oldest part: LUCENE-9147 "Move the stored fields index off-heap" (apache/lucene-solr#1179, migrated issue #10187), jpountz, 136dcbdbbce (main) / 597141df6b6 (branch_8x), 2020-02-05, first in 8.5.0: it started writing .fdm and .tvm, documented .fdm on the stored-fields page and touched no package-info. The 8.4.1 and 8.5.0 tables are the same apart from one unrelated link.
  • Later layers (none put its file in the table: #12582 wrote the vector row's current text, #13585 copied the table into its new lucene912 package without a .psm row, the other four touched no package-info): .tmd 87a3bef50f8 / 0dac659cd17 (LUCENE-9353, lucene-solr#1473, jpountz, 8.6.0); the vector row .vec, .vem, .veq, vex f2bf5339e53 (#12582, benwtrent, written when the HNSW format could still write .veq) and a47ba3369f4 (#12729, benwtrent: .veq moved to separate formats, .vemf added, row untouched), both 9.9.0; .psm b4a8810b7ae (#13585, jpountz, 9.12.0); .dvs 37b6d65a7d6 (#15976, romseygeek, 10.5.0); .dvp 1160d3c8a25 (#16540, sgup432, 10.6.0).
  • The undotted vex: 9.9.0-10.1.0 and 10.3.0 on; 10.2.x had .vex (#14078 had moved the overview to lucene102/package-info.java while the default codec stayed Lucene101; that row also listed .veb, .vemb), and 10.3.0 brought the old text back (#14333 / #14563).
  • Out of scope: the stale points row of 8.6.0-9.12.x, fixed for 10.0.0 by #13801.
  • An earlier, superseded vector-row gap: from 9.0.0 (LUCENE-9004, b36b4af22bb, the first vector format, which writes .vex) through 9.8.0 the row read .vec, .vem and lacked .vex; #12582 replaced it in 9.9.0. The executed 9.8.0 run reports [fdm, tmd, tvm, vex] missing and the row [.vec, .vem] against the written [vec, vem, vex].
  • Caveats: 53 releases affected. This follow-up executed 12 of them (plus the clean 8.4.1, and main); with the study's 2026-10-28 run, 22 distinct affected releases have been executed. The rest are inferred, not run: from the executed releases on either side, each with its own default codec and table, from the study's extraction of the table's extensions at every 8.0.0-10.5.2 tag, and from the table's history (8.8.2-8.11.3 are not tagged in the history clone). JDK 25 on Linux aarch64 only.
Versions and branches executed, with results
Version or commitVerdictResult
main 645d4fe14a20 affectedthe minimal repro fails with assertions on and off; the version-aware check fails all four parts (missing, vector row, dot, postings list)
10.6.0, 10.5.2, 10.5.0, 10.4.0 affectedthe minimal repro reports 7 (10.6.0), 6 (10.5.2) and 5 (10.4.0) missing extensions; 10.5.0 ran the version-aware check only; .dvp from 10.6.0, .dvs from 10.5.0
9.12.0, 9.11.1, 9.9.0 affectedmissing .fdm, .tmd, .tvm, .vemf (and .psm from 9.12.0); vector row wrong; vex undotted
9.8.0 affectedmissing .fdm, .tmd, .tvm and .vex: the vector row .vec, .vem lacks .vex, written since 9.0.0; postings list misses .tmd
8.11.4, 8.6.0, 8.5.2, 8.5.0 affectedmissing .fdm, .tvm (from 8.5.0) and .tmd (from 8.6.0)
8.4.1, 8.0.0 not affectedthe table lists every file the default codec writes (8.4.1 with assertions on and off)

Independent checks

Confirmed by an independent reproducer, reviews by a reviewer from another model family (OpenAI GPT-5.6), an intended-behaviour devil's advocate and an adjudication (high confidence); an audit confirmed it as a low-priority doc defect; re-checked on 645d4fe14a20. This doc's gradle run validated the fix.

Checks and verdicts435 words

Every check either re-ran a test or read the same table and writer lines; none found a reading under which the table is meant to leave these files out or credit .veq to the default format.

Each independent check and its verdict
CheckVerdictWhat it found
finder (a hunt unit) reproducedDifferential check over 91 generated indexes (a separate 41-configuration sweep checked the fixed text); its 3-test JUnit fails 3 of 3 on main (on and off), the 10.6.0 release commit and 10.5.2.
cross-model review, refute lens (OpenAI GPT-5.6, executing; study) real, high confidenceOwn audit on three seeds reproduced the missing sets and the vector-row mismatch; a compound control passes; with the fix text its check passes; intended argument moderate.
independent reproducer realOwn check that parses the table and the list from source: 4 of 4 fail on main (on and off), 10.5.2 and 9.12.3; 0 failures with the fix text.
cross-model review, intended lens (OpenAI GPT-5.6, reading only) real, medium confidenceIt could not run any code, so it read only; a separate run re-ran the finder's test: 3 of 3 fail on and off. Noted that the .dvp CHANGES entry cites issue #16298 (the PR is #16540).
intended-behaviour devil's advocate real (documentation defect)Built and rejected the "high-level summary" case; found no version of the table with a .fdm, .tmd, .psm or .vemf cell; moderate on the .veq wording.
adjudication confirmed, high confidence, documentation defect, minorRe-ran the independent reproduction's check with a fresh seed on main, on and off (4 failures each), and read the source.
credibility audit confirmed, minorRe-ran the finder's test on new seeds: 3 of 3 fail. Its committer-perspective note (the auditor's own view, not a Lucene committer's): "I'd merge this as a small doc PR, the same way as #13801. It's a real but cosmetic documentation defect."
re-check on 645d4fe14a20 and a second refute review (2026-11-01) real, high confidenceThe minimal repro fails on main and 10.5.2, on and off; the control with the seven extensions added passes. The second cross-model review's own test parses the real table with a file-system directory and finds the same seven plus the undotted vex; its compound control passes.
this doc's validation (2026-11-01) fix A validatedIn a scratch worktree with fix A: the version-aware check on the fixed text reports 0 failures (on and off; 4 on the stock text); TestLucene104PostingsFormat with the updated repro (35 tests), checkGoogleJavaFormat, :lucene:core:check -x test and renderJavadoc pass; the repro fails through gradle on stock, on and off.

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,531 words

Finding record

LFV-972, snapshot of 2026-11-06

Registry title
The default codec's 'Summary of File Extensions' table (codecs/lucene104 package documentation) is stale: it omits .fdm, .tvm, .tmd, .psm, .dvs, .dvp and .vemf, which the default codec writes, credits .veq to the default HNSW vectors format (which does not write it) and gives 'vex' without its dot; Lucene104PostingsFormat's 'Files and detailed format' list also omits .tmd and .psm (documentation defect; the code is correct)
Area
codecs / default codec file-format overview (codecs/lucene104 package-info 'Summary of File Extensions' table and the Lucene104PostingsFormat 'Files and detailed format' list vs the files the default codec writes)
Priority
Low, rank 1281: The stale extension table in the default codec overview leaves out common files, but the per-format javadocs list nearly all of them and it is a missing-name list, not a wrong byte grammar.
Impact class
minor
Impact note
Documentation only: Lucene's writers and readers are unaffected in every configuration; the people misled are readers of the published File Formats overview and of the Lucene104PostingsFormat file list (people who inspect, size or copy index directories by extension, or write format tools from the overview), who find .fdm, .tmd and .psm (written for almost every default-codec index) and .tvm, .dvs, .dvp and .vemf unlisted and a .veq that the default vectors format never writes; the linked per-format javadocs already document every missing file except .psm; the drift began in 8.5.0 (2020) and needs no scale or special setting.
Summary
You index ordinary documents with the default codec and look up the files in the index directory in the 'Summary of File Extensions' table of the codec's package documentation, which says it 'summarizes the names and extensions of the files' of this format version. Seven extensions the default codec writes are missing (.fdm, .tvm, .tmd, .psm, .dvs, .dvp, .vemf); the vector row lists '.vec, .vem, .veq, vex', but the default Lucene99HnswVectorsFormat it links writes .vec, .vemf, .vem and .vex (.veq comes only from the optional scalar-quantized formats) and 'vex' lacks its dot; and Lucene104PostingsFormat's own 'Files and detailed format' list leaves out .tmd and .psm. Lucene itself reads and writes all these files correctly; each format change since 8.5.0 that added a file updated at most its own class javadoc, never this overview.
Introduced
accumulated staleness, one layer per format change [follow-up, boundaries executed]. Earliest still-present layer: 136dcbdbbce (main) / 597141df6b6 (branch_8x, first in 8.5.0), LUCENE-9147 'Move the stored fields index off-heap' (apache/lucene-solr#1179, migrated issue apache/lucene#10187), by jpountz: it started writing .fdm and .tvm and documented .fdm in the stored-fields format javadoc but not in the codec table [exec: 8.4.1 pass, 8.5.0 fail]. Later layers: 87a3bef50f8 / 0dac659cd17 (LUCENE-9353, apache/lucene-solr#1473, jpountz: .tmd, 8.6.0); f2bf5339e53 / 6623c42553b (#12582, benwtrent: wrote the '.vec, .vem, .veq, vex' row while the HNSW format itself still wrote .veq) and a47ba3369f4 / 448e6112954 (#12729, benwtrent: moved .veq to separate formats and added .vemf without touching the row), both first in 9.9.0; b4a8810b7ae / 59b7c28eb47 (#13585, jpountz: .psm, 9.12.0); 37b6d65a7d6 / 71a214ce53c (#15976, romseygeek: .dvs, 10.5.0); 1160d3c8a25 / 977dfa876d2 (#16540, sgup432: .dvp, 10.6.0). The undotted 'vex' was dotted in 10.2.x (#14078) and came back in 10.3.0, when #14333 / #14563 created lucene103/package-info.java from the older text. Correction of an earlier attribution: LUCENE-9456 (8.7.0) only moved more metadata into the existing .fdm and .tvm files (8.6.3 and 8.7.0 write the same set) (2020-02-05 (author date of 136dcbdbbce and 597141df6b6: .fdm and .tvm); later layers 2020-06-16 (.tmd), 2023-10-24 and 2023-11-10 (the vector row), 2024-07-31 (.psm), 2026-04-22 (.dvs), 2026-09-11 (.dvp))
First affected version
8.5.0 [exec] (.fdm and .tvm missing; the last unaffected release is 8.4.1 [exec], and 8.0.0 also passes); the wrong vector row (.veq credited to the default format, .vemf missing, undotted 'vex') from 9.9.0 [exec]
Affected versions
every release from 8.5.0 through 10.6.0 (the branch_10_6 head 4ae946e5a9b) and main a9779ef3c193; not fixed upstream. By part [follow-up]: .fdm/.tvm 8.5.0-10.6.0; .tmd (table and postings list) 8.6.0-10.6.0; .veq misattributed and .vemf missing 9.9.0-10.6.0 (the 10.2.x row also lists .veb/.vemb); undotted 'vex' 9.9.0-10.1.0 and 10.3.0-10.6.0 (dotted in 10.2.0-10.2.2; 10.6.0 by reading); .psm (table and postings list) 9.12.0-10.6.0; .dvs 10.5.0-10.6.0; .dvp 10.6.0, branch_10x and main [exec: the follow-up's version-aware check, which parses each release's own table and postings list and indexes with that release's default codec, passes on 8.0.0 and 8.4.1 and fails on 8.5.0, 8.5.2, 8.6.0, 8.6.3, 8.7.0, 8.8.1, 8.11.4, 9.0.0, 9.8.0, 9.9.0, 9.11.1, 9.12.0, 9.12.3, 10.0.0, 10.1.0, 10.2.0, 10.2.2, 10.3.0, 10.4.0, 10.5.0, 10.5.2 and main (-ea and -da), and passes on main with the fix text applied; the finder's JUnit fails 3 of 3 on main (-ea and -da), the branch_10_6 head, 10.4.0, 10.5.0 and 10.5.2 (2 of 3 on 10.0.0, where its postings check is vacuous because 10.0 writes Lucene912 postings); the independent reproduction's check fails on main, 10.5.2 and 9.12.3]. 8.8.2-8.11.3 are inferred (not tagged in the history clone; same codec, and the 8.8.1 and 8.11.4 tables are identical). Out of scope: the 8.6-9.12 stale points row, fixed for 10.0.0 by #13801. Caveats: all runs used JDK 25.0.3 on Linux aarch64; upstream main 645d4fe14a20 (2026-10-28) has not changed either file
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
semi-formal
Upstream and prior reports
none found (searched 2026-10-28: three scripted prior-report searches (48 GitHub, 9 commit, 6 downstream, 60 mailing-list and 12 JIRA-archive queries over dev@, java-user@, issues@, commits@) plus the finder's run (51 queries), 14 more issue and PR queries on apache/lucene, 18 on downstream repositories, 5 more searches and 9 web searches; all 414 open apache/lucene PRs enumerated by changed files). Nearest items, not the same bug: #13801 (romseygeek, merged 2024-09-18, 'Correct Point file extensions in Codec javadocs': fixed only the points row of the same table, '.dii, .dim' to '.kdd, .kdi, .kdm', and names no other row; an earlier fix of the same kind); #10744 / LUCENE-9705 (a 2021 comment by msokolov that package javadocs were copied 'pretty inconsistently over time'; names no table or extension); the changes that made the text stale (apache/lucene-solr#1179, #1473 and #1752, #12582, #12729, #13585, #15976, #16540; none of their threads discusses the table); #90 (revised only the blocktree writer javadoc for .tmd); #15625 (the last Lucene104PostingsFormat javadoc fix, a different sentence). Not a fix: open PR #16480 touches lucene104/package-info.java only to add a History bullet; open PR #16911 deletes branch_10x. Recheck (2026-10-28): six issue and PR searches, including items created or updated in the last 48 hours, found no report; none of the 20 PRs created since 2026-10-26 touches either file; by author date the latest upstream commits are 00f2b01e798 (2025-09-10, #15160) for package-info.java and 19bf11ddad8 (2026-01-28, #15625) for Lucene104PostingsFormat.java, so upstream main 645d4fe14a20 still has the stale table and list. Not fixed upstream. Update 2026-11-02: #16911 (open when searched) merged 2026-10-29 as 48cf3f515d6, which emptied branch_10x to a README tombstone (10.6 is the last 10.x minor; 10.x fixes go to branch_10_6); it fixes nothing here.
Lucene commit tested
main 645d4fe14a20: the minimal repro with assertions on and off, standalone (seed DEADBEEF) and through gradle in a scratch worktree (on and off); the fix in that worktree: the version-aware text check (on and off), TestLucene104PostingsFormat with the repro's updated form, :lucene:core:checkGoogleJavaFormat, :lucene:core:check -x test and :lucene:core:renderJavadoc. The minimal repro on the 10.4.0, 10.5.2 and 10.6.0 release jars; the version-aware check on 8.4.1 (pass), 8.5.0, 8.5.2, 8.6.0, 8.11.4, 9.8.0, 9.9.0, 9.11.1, 9.12.0, 10.4.0, 10.5.0, 10.5.2, 10.6.0 and main. Both fix-site files have the same blobs on 645d4fe14a20 and on upstream main f815e679bf6c (2026-11-01) (read).

Lucene and upstream sources

Finding record
  • lucene/core/src/java/org/apache/lucene/codecs/lucene104/package-info.java:50 ('defines the index file formats used in this version of Lucene'), :54 ('a high-level definition'), :188 ('Details on each of these are provided in their linked pages'), :211 ('summarizes the names and extensions of the files in Lucene'), :289 ('.dvd, .dvm'), :312-318 (vector row '.vec, .vem, .veq, vex' linked to Lucene99HnswVectorsFormat); Lucene104PostingsFormat.java:81-89 ('Files and detailed format': .tim, .tip, .doc, .pos, .pay), :324-325 (META_EXTENSION = "psm") [read at the follow-up step, clean checkout]
The finding in 30 seconds
  • lucene/core/src/java/org/apache/lucene/codecs/lucene104/package-info.java (lines 50, 54, 188, 194-197, 207-319: the table; 289 doc-values row; 312-318 vector row)
  • lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104PostingsFormat.java (lines 81-89 'Files and detailed format'; 324-325 META_EXTENSION psm; 410-413 fieldsConsumer)
  • lucene/core/src/java/org/apache/lucene/codecs/lucene90/compressing/Lucene90CompressingStoredFieldsWriter.java (67, 131-132), lucene90/compressing/Lucene90CompressingTermVectorsWriter.java (69, 259-260), lucene103/blocktree/Lucene103BlockTreeTermsReader.java (84), lucene103/blocktree/Lucene103BlockTreeTermsWriter.java (91, 147, 321-324), lucene104/Lucene104PostingsWriter.java (153)
  • lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90DocValuesFormat.java (135-136, 195, 197), lucene90/Lucene90DocValuesConsumer.java (110, 120), lucene99/Lucene99FlatVectorsFormat.java (48, 81), lucene99/Lucene99FlatVectorsWriter.java (111-120), lucene99/Lucene99HnswVectorsFormat.java (89-90, 155-156), lucene104/Lucene104ScalarQuantizedVectorsFormat.java (107-108), lucene104/Lucene104Codec.java (71, 120-123), lucene90/Lucene90StoredFieldsFormat.java (92), lucene90/Lucene90TermVectorsFormat.java (54)
Who is affected
  • lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java (99), index/DocumentsWriterPerThread.java (643), index/LiveIndexWriterConfig.java (143), index/MergePolicy.java (598-600), codecs/CompoundFormat.java (42, 54, 163-179)
Why it looks unintended
  • lucene/core/src/java/org/apache/lucene/codecs/lucene104/package-info.java (lines 50, 54, 188, 211, 289, 312-318)
  • lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104Codec.java (line 53 @lucene.experimental)
Suggested fix
  • lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104PostingsWriter.java (153, 711-720: what .psm holds)
  • lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene99/package-info.java and lucene103/package-info.java (line 314: the same vector row)

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

Repro files

About the diagrams

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.