All findings · Lucene finding · LFV-959 · main-11-0-notes-omit-doc-values-overlays-default-on

Lucene 11.0 (main) turns incremental doc-values updates on by default, but neither its release notes nor the migration guide say so

Lucene 10.6 ships incremental doc-values updates as opt-in; 11.0 (main and branch_11x today) turns them on by default with 8 overlays per field. Its release-note entry still says "Opt-in" and MIGRATE.md says nothing, so a 10.6-to-11.0 upgrader gets a different update write path without being told.

Summary

Priority
Low, rank 1262The release notes and MIGRATE.md omit a default change on unreleased main that every 11.0 doc-values-update user meets while results stay correct.
Impact
minor
Since
2026-09-01 on main (ea248114ac4; completed by 7cecf795236 on 2026-10-21)introduced 2026-09-01
Affected
main and branch_11x (unreleased 11.0); 10.6.0 is documented correctly
Status
documented
Found by
non-formal: the release notes read against the code, plus a differential test

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

Lucene 10.6 added incremental doc-values updates, off unless you turn them on. Lucene 11.0 (main and branch_11x) turns them on for everyone (DEFAULT_MAX_DOC_VALUES_OVERLAYS 0 -> 8). Main's own note saying so was moved into the 10.6.0 section and reworded to 10.6.0's correct "Opt-in" text, so the 11.0 notes say nothing.

Background: doc-values updates and overlays

  1. A doc-values update (IndexWriter.updateNumericDocValue, updateBinaryDocValue, updateDocValues) changes a column value of existing documents without re-indexing them.
  2. Without overlays, Lucene writes each update as a new copy of the field's whole column in that segment.
  3. With incremental updates (new in 10.6), a set-only update is written as a small sparse overlay holding only the changed documents. A field keeps up to N overlays, then folds them into one; N = 0 turns the feature off.
Diagram of the bug: Lucene 10.6.0 has incremental doc-values updates off by default and its notes say Opt-in; main, the future 11.0, has them on with 8 overlays per field, while its 11.0.0 CHANGES section and MIGRATE.md say nothing, so the note an upgrader finds is the 10.6.0 Opt-in entry.
The default on each line (0 in 10.6.0, 8 on main), what one update writes under each, where the notes record it, how main's 11.0 note was lost, and the text-only fix. Select the still to open it at full size. Generated with AI, checked against the code.

The finding, step by step

  1. On Lucene 10.6 you update a document with IndexWriter.updateNumericDocValue and a default IndexWriterConfig. Incremental doc-values updates are opt-in there (DEFAULT_MAX_DOC_VALUES_OVERLAYS = 0), so the update rewrites the field's whole column.
  2. You plan the upgrade to 11.0 (main and branch_11x today) and read the 11.0 section of CHANGES.txt and MIGRATE.md. You expect a note if this default changed, as both give one for the query cache, which 11.0 turns off by default.
  3. Instead main's default is 8 overlays per field: updating 1 of 1,000 documents writes a 402-byte sparse overlay instead of the 2,892-byte column rewrite you get with the feature off, and up to 8 overlays per field stay live, each with its own files.
  4. The feature's entry (GITHUB#16418) sits in the 10.6.0 section and says "Opt-in; enable with IndexWriterConfig#setMaxDocValuesOverlays(n)". The 11.0.0 section and MIGRATE.md have 0 lines on it. Main had an "Enabled by default" entry until two changelog edits moved it to 10.6.0 and reworded it there.
  5. Search results stay correct, so this is a missing note, not a code bug: one CHANGES line and a short MIGRATE section with the opt-out setMaxDocValuesOverlays(0) fix it.

Who is affected

Applications that upgrade from 10.x to 11.0, keep the default IndexWriterConfig and call the doc-values update methods. Their set-only updates silently switch to overlay files, with more live files and open file handles per field (the concern that lowered the default from 16 to 8). Results stay correct, and nothing in the 11.0 notes points them to the opt-out.

Mechanism, terms and numbers695 words

Lucene 10.6.0 added incremental doc-values updates (GITHUB#16418): a doc-values update that only sets values is written as a small sparse overlay holding just the updated documents, layered over the column at read time, instead of a rewrite of the whole column. In 10.6 the feature is off unless the application calls IndexWriterConfig#setMaxDocValuesOverlays(n) (DEFAULT_MAX_DOC_VALUES_OVERLAYS = 0). On main and branch_11x, the future 11.0, it is on by default with up to 8 overlays per field (IndexWriterConfig.java:115), deliberately: the #16418 PR says "On main the feature is on by default".

The release notes do not record that difference. The only GITHUB#16418 entry in CHANGES.txt sits in the 10.6.0 section and says "Opt-in; enable with IndexWriterConfig#setMaxDocValuesOverlays(n)" (CHANGES.txt:501-504), correct for 10.6.0. The 11.0.0 "Changes in Runtime Behavior" list has only "The query cache is now disabled by default" (:341-343), and MIGRATE.md's 10.x-to-11.0 guide has no line on overlays, although it gives the query-cache flip a section with the code to undo it (MIGRATE.md:227-236). Main had an 11.0.0 entry saying "Enabled by default; disable with IndexWriterConfig#setMaxDocValuesOverlays(0)" until ea248114ac4 (2026-09-01) moved it to the 10.6.0 section and the 10.6.0 sync 7cecf795236 (2026-10-21) reworded it to the 10.6.0 text.

An application that upgrades from 10.6 to 11.0 with a default IndexWriterConfig and uses doc-values updates therefore moves to the overlay write path, with more live files per field, and nothing in the 11.0 notes tells it. Results stay correct, and in the measured example (1 of 1,000 documents) the update wrote 402 instead of 2,892 bytes. The fix is text only: an 11.0.0 CHANGES entry and a MIGRATE.md section with the opt-out. Upstream main (now 12.0.0-SNAPSHOT, with 11.0.0 as its second section) and branch_11x still lack it on 2026-11-01.

The code (main 645d4fe14a20)

// IndexWriterConfig.java:110-115
/**
 * Default maximum number of sparse doc-values overlays a field keeps before they are folded into
 * one: {@code 8}. {@code 0} disables the feature (classic full-column rewrite); higher values
 * lower write amplification but keep more overlays (hence more files) live to merge at read time.
 */
public static final int DEFAULT_MAX_DOC_VALUES_OVERLAYS = 8;

// ReadersAndUpdates.java:363
final boolean sparseDelta = config.getMaxDocValuesOverlays() > 0 && anyRemoval == false;
  • Every new config takes the default (LiveIndexWriterConfig.java:146). The setter's javadoc says "Enabled by default (see {@link #DEFAULT_MAX_DOC_VALUES_OVERLAYS})." and "Only takes effect when IndexWriter is first created." (IndexWriterConfig.java:342, :344); the setter is @lucene.experimental (:346), the update methods are not (IndexWriter.java:1962, :1996, :2037, :2070).
  • The write path. A set-only update becomes a sparse delta generation (ReadersAndUpdates.java:363); once a field has 8 deltas the next write folds them into one (:368). The comment at :358-362 says single-valued sorted-numeric updates take the same path (GITHUB#16580, CHANGES.txt:523-527).
  • 10.6.0 (tag 4ae946e5a9b): IndexWriterConfig.java:116 is = 0 and :343 says "Disabled by default"; its CHANGES.txt has the same "Opt-in" entry. 10.6.0 is consistent.

The notes (main 645d4fe14a20)

wherewhat it says about the feature
CHANGES.txt 11.0.0, "Changes in Runtime Behavior" (:341-343)nothing; the list has only "GITHUB#14187: The query cache is now disabled by default."
CHANGES.txt 10.6.0 (:501-504), the only GITHUB#16418 entry"... Opt-in; enable with IndexWriterConfig#setMaxDocValuesOverlays(n). (Jim Ferenczi)"
MIGRATE.md, "Migration from Lucene 10.x to Lucene 11.0" (:20)0 lines; it has sections for other default changes, among them the query cache (:227-236) and the filtered-HNSW threshold (:238-244)

How the 11.0 note was lost

  1. 75eddfaff22 (PR #16418, 2026-08-13): the feature lands on main, default 16, with an 11.0.0 entry ending "Enabled by default; disable with IndexWriterConfig#setMaxDocValuesOverlays(0)".
  2. ea248114ac4 (2026-09-01, "Rename SegmentInfos.VERSION_11_0 to VERSION_10_6", pushed without a PR): the entry moves unchanged from 11.0.0 to 10.6.0, the day the opt-in 10.x backport (#16554) lands. The 11.0.0 section now says nothing.
  3. 92d9f2c7faa (PR #16648, 2026-09-08): default 16 -> 8; its commit message says "The feature is not yet released, so no CHANGES entry is needed."
  4. 7cecf795236 (2026-10-21, "Ensure 10.6.0 changelog in main is consistent with branch_10_6", pushed without a PR): the moved entry gets 10.6.0's "Opt-in" text. Correct for 10.6.0, but no "enabled by default" wording is left in main's notes.
Exposure and likelihood271 words
  • Who. Applications that use doc-values updates (updateNumericDocValue, updateBinaryDocValue, updateDocValues; single-valued sorted-numeric updates per GITHUB#16580) and upgrade to 11.0 with a default IndexWriterConfig. No opt-in or rare setting is needed; the update methods are public and not experimental.
  • What changes. Set-only updates write sparse overlays instead of a full column (402 instead of 2,892 bytes of update files for 1 of 1,000 documents in the measured example), and up to 8 overlays per field stay live until a fold, so more files are live per field and reads merge them (IndexWriterConfig.java:110-114). #16648 lowered the default from 16 to 8 because "open file handles scale with segments times updated fields times the overlay budget", after a CI open-handle guard tripped (#16644).
  • What does not change. Search results: the updated values read back correctly in every mode an independent reproducer tested, and nothing threw in those runs.
  • Upgraders run into it. A downstream issue names this default as one of two Lucene 11 changes that affect a test failing against the Lucene 11 snapshot (elastic/elasticsearch#163787, 2026-10-28: "It also turns on doc-values overlays by default (DEFAULT_MAX_DOC_VALUES_OVERLAYS 0→8)"). It names the constant and does not cite Lucene's CHANGES or MIGRATE; the test still fails "despite the adjustments made", so the issue does not show the default to be the cause.
  • Scale. Every such upgrader whose updates only set values (updates with removals still rewrite the whole column, ReadersAndUpdates.java:363), with no data-size threshold. Unreleased: no release ships the default without a note yet; 11.0.0 would be the first. Impact class minor: a documentation defect with no wrong results.

Minimal repro

No unit test can show a missing note, so the repro is a read-only shell check of a Lucene checkout. It prints the code default and the CHANGES.txt lines naming GITHUB#16418, "Opt-in;" or MaxDocValuesOverlays with their release section, then counts lines of the 11.0.0 section and of MIGRATE.md with its search terms; it exits 1 when both are 0.

check_11_0_notes.sh (read-only, no build)23 lines
#!/bin/sh
# Do Lucene's 11.0 upgrade notes say that incremental doc-values updates are now on by default?
# Usage: sh check_11_0_notes.sh "$LUCENE"      ($LUCENE: a Lucene checkout of main or branch_11x)
# Exit 0 when the 11.0.0 section of CHANGES.txt or MIGRATE.md has a line with one of the search terms
# (16418, MaxDocValuesOverlays, overlay), 1 when neither does. A term search: read the sections too.
set -eu
cd "$1/lucene"
IWC=core/src/java/org/apache/lucene/index/IndexWriterConfig.java
echo "code default: $(grep -o 'DEFAULT_MAX_DOC_VALUES_OVERLAYS = [0-9]*' "$IWC")"
# the CHANGES.txt lines naming GITHUB#16418, Opt-in; or MaxDocValuesOverlays, with their release section
awk '/^=+ Lucene [0-9.]+ =+$/ { sec = $3 }
     /GITHUB#16418|Opt-in;|MaxDocValuesOverlays/ { printf "CHANGES.txt:%d [%s] %s\n", NR, sec, $0 }' CHANGES.txt
n11=$(awk '/^=+ Lucene [0-9.]+ =+$/ { on = ($3 == "11.0.0") }
           on && /16418|MaxDocValuesOverlays|[Oo]verlay/' CHANGES.txt | wc -l)
nmig=$(grep -c -i 'MaxDocValuesOverlays\|overlay' MIGRATE.md || true)
echo "lines on it in the 11.0.0 section of CHANGES.txt: $n11"
echo "lines on it in MIGRATE.md: $nmig"
if [ "$n11" -gt 0 ] || [ "$nmig" -gt 0 ]; then
  echo "OK: the 11.0 notes record the feature"
else
  echo "MISSING: no 11.0 note says the default changed"
  exit 1
fi
Command
sh check_11_0_notes.sh "$LUCENE"     # $LUCENE: a Lucene checkout of main or branch_11x
Expected
At least one 11.0 note on the new default: a line in the 11.0.0 section of CHANGES.txt or in MIGRATE.md, as the query-cache flip has in both.
Observed
DEFAULT_MAX_DOC_VALUES_OVERLAYS = 8; the only GITHUB#16418 entry is the 10.6.0 "Opt-in" one (lines 501-504); 0 lines in the 11.0.0 section, 0 in MIGRATE.md; exit status 1.

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

More files, environment, full output378 words

The hunt's JUnit (TestDocValuesOverlaysDefaultAsReleaseNotes) is not used as the repro: it asserts the 10.6.0 "Opt-in" note against main, which main's own javadoc contradicts, so it shows only that the default differs. On main 645d4fe14a20 it fails 2 of 2 with -ea and -da (new IndexWriterConfig().getMaxDocValuesOverlays() is 8; "with the default config an update of 1 of 1000 documents wrote 402 bytes of update files, with setMaxDocValuesOverlays(0) 2892 bytes"); on jars built locally from the 10.6.0 tag commit 4ae946e5a9b it passes (the default config and setMaxDocValuesOverlays(0) write the same number of bytes of update files). The step numbers come from that run.

No regression test is suggested: a test that greps CHANGES.txt would assert a project practice that no document promises.

The check is a term search: a note worded without its terms (say, only "incremental doc-values updates") would not be counted.

With the recommended fix applied to 645d4fe14a20, the same check prints:

# sh check_11_0_notes.sh $LUCENE   (scratch worktree of 645d4fe14a20 + fix-recommended-645d4fe.diff, 2026-11-01)
code default: DEFAULT_MAX_DOC_VALUES_OVERLAYS = 8
CHANGES.txt:345 [11.0.0] * GITHUB#16418, GITHUB#16648: Incremental doc-values updates, opt-in in 10.6, are now enabled by default:
CHANGES.txt:346 [11.0.0]   IndexWriterConfig#DEFAULT_MAX_DOC_VALUES_OVERLAYS is 8. Pass IndexWriterConfig#setMaxDocValuesOverlays(0)
CHANGES.txt:505 [10.6.0] * GITHUB#16418: Incremental doc-values updates. A set-only doc-values update (NUMERIC or BINARY) is written as a sparse
CHANGES.txt:507 [10.6.0]   rewriting the whole column, turning per-update write amplification from O(column) into O(updated docs). Opt-in;
CHANGES.txt:508 [10.6.0]   enable with IndexWriterConfig#setMaxDocValuesOverlays(n). (Jim Ferenczi)
lines on it in the 11.0.0 section of CHANGES.txt: 2
lines on it in MIGRATE.md: 3
OK: the 11.0 notes record the feature
exit=0

Environment

lucenemain 645d4fe14a20 (11.0.0-SNAPSHOT); same result on the upstream files of main f815e679bf6c and branch_11x da3ea39fa597 (2026-11-01)
jdknot needed for the check (the behaviour numbers: OpenJDK 25.0.3)
osLinux aarch64; any POSIX sh with awk and grep

Observed output

# sh check_11_0_notes.sh $LUCENE   (main 645d4fe14a20, 2026-11-01)
code default: DEFAULT_MAX_DOC_VALUES_OVERLAYS = 8
CHANGES.txt:501 [10.6.0] * GITHUB#16418: Incremental doc-values updates. A set-only doc-values update (NUMERIC or BINARY) is written as a sparse
CHANGES.txt:503 [10.6.0]   rewriting the whole column, turning per-update write amplification from O(column) into O(updated docs). Opt-in;
CHANGES.txt:504 [10.6.0]   enable with IndexWriterConfig#setMaxDocValuesOverlays(n). (Jim Ferenczi)
lines on it in the 11.0.0 section of CHANGES.txt: 0
lines on it in MIGRATE.md: 0
MISSING: no 11.0 note says the default changed
exit=1

Why it looks unintended

  • Lucene lists default flips: this 11.0.0 "Changes in Runtime Behavior" list has "The query cache is now disabled by default", and MIGRATE.md gives it a section.
  • Main had the note ("Enabled by default") until a commit renaming a SegmentInfos constant moved it to 10.6.0.
  • #16648 skipped an entry because the feature was "not yet released"; 10.6.0 shipped it on 2026-10-29.
The full argument254 words
  • The project's own practice. Default changes are listed under "Changes in Runtime Behavior": in this 11.0.0 section "GITHUB#14187: The query cache is now disabled by default." (CHANGES.txt:343), and earlier "GITHUB#15040: The default ReadAdvice has been changed from RANDOM to NORMAL" (10.3.0, :1739) and "GITHUB13293: Auto I/O throttling is now disabled by default on ConcurrentMergeScheduler" (10.0.0, :2403). MIGRATE.md's 11.0 guide has sections for other default changes, among them the query cache (:227-236) and the filtered-HNSW threshold (:238-244).
  • The record existed and was lost as a side effect. The 11.0.0 entry said "Enabled by default" until ea248114ac4, a commit about renaming a SegmentInfos constant, moved it to 10.6.0; the 10.6.0 sync then reworded it, correctly for 10.6.0. No PR, issue or dev@ thread found discusses leaving 11.0 without a note.
  • The one "no CHANGES entry" decision was about something else. #16648's commit message skips an entry for the 16 -> 8 step because "the feature is not yet released". It was written while main's entry still said "Enabled by default" (by then under 10.6.0), and its premise ended when 10.6.0 shipped the feature opt-in (tag 2026-10-29).
  • Upstream merges this kind of fix. #16912, "Move CHANGES entry for GITHUB#16794 from 10.6.0 to 11.0.0", was merged on 2026-10-26.
  • What is not claimed. That the code is wrong (default-on is deliberate and documented in the javadoc), that the 10.6.0 entry is wrong, that results change, or anything about soft-delete updates or BINARY updates beyond the CHANGES text (not tested separately).
The devil's-advocate check234 words

Strongest case for "intended / noise". Default-on is deliberate and documented where the API is documented: IndexWriterConfig.java:342 says "Enabled by default", the #16418 and #16554 PR texts state the main/10.x difference, and TestIncrementalDocValuesUpdates.testDefaultBudgetHeavyStackingAndFolding "Exercises the shipping default overlay budget". The setter is @lucene.experimental. CHANGES entries are optional (CONTRIBUTING.md:107: "You may want to add a CHANGES entry"), the release manager distills the release notes from CHANGES.txt before a release (dev-tools/scripts/releaseWizard.yaml:606-610), and 11.0 is unreleased. The 10.6.0 entry is correct for 10.6.0, and results never change. The cross-model refute lens argued this and rated it not real; an intended-behaviour verifier built the same case.

Why it fails. It defeats the framing "the code is wrong", which nobody claims, not the narrow claim. Nothing shows that the 11.0 record was meant to go (the history shows the edits, not their intent, and no discussion found decides it): the javadoc of an experimental setter that an upgrader keeping the defaults has no reason to call is not where upgraders look; the same section and MIGRATE.md record the analogous flips; the record existed and disappeared through two changelog edits; and the release manager's draft starts from CHANGES.txt, so an explicit entry is the direct way into it. The refute lens conceded that neither the 11.0 CHANGES nor MIGRATE records the change. The adjudication ruled that these points go to severity (minor), not to reality.

Suggested fix

Recommended CHANGES entry plus MIGRATE section

Add an 11.0.0 "Changes in Runtime Behavior" entry next to the query-cache one, and a short MIGRATE.md section with the opt-out setMaxDocValuesOverlays(0). Checked on 645d4fe14a20: the notes check passes, CHANGES and MIGRATE render, and the closest core suites pass (24 tests).

All options and trade-offs4 options · 508 words

Text-only fixes. Upstream main now has a 12.0.0 section on top, so the entry goes into main's 11.0.0 section and is backported to branch_11x; the anchors are the GITHUB#14187 entry and the query-cache MIGRATE section.

CHANGES entry plus MIGRATE section (validated by the checks) (recommended)

An entry under 11.0.0 "Changes in Runtime Behavior", next to GITHUB#14187, and a MIGRATE.md section after "Query caching is now disabled by default" that says what changed and how to keep the 10.x behaviour.

--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -342,6 +342,10 @@ Changes in Runtime Behavior
 ---------------------
 * GITHUB#14187: The query cache is now disabled by default. (Adrien Grand)
 
+* GITHUB#16418, GITHUB#16648: Incremental doc-values updates, opt-in in 10.6, are now enabled by default:
+  IndexWriterConfig#DEFAULT_MAX_DOC_VALUES_OVERLAYS is 8. Pass IndexWriterConfig#setMaxDocValuesOverlays(0)
+  to keep rewriting the whole column on every doc-values update. (Jim Ferenczi)
+
 Build
 ---------------------
 * GITHUB#15327: New low-level build options to detect abuse of LuceneTestCase.random():
--- a/lucene/MIGRATE.md
+++ b/lucene/MIGRATE.md
@@ -235,6 +235,21 @@ long maxRamBytesUsed = 50 * 1024 * 1024; // 50MB
 IndexSearcher.setDefaultQueryCache(new LRUQueryCache(maxCachedQueries, maxRamBytesUsed));
 ```
 
+### Incremental doc-values updates are enabled by default (GITHUB#16418, GITHUB#16648)
+
+Incremental doc-values updates, opt-in in Lucene 10.6, are now enabled by
+default. A doc-values update that only sets values (no removals) is written as
+a sparse overlay holding just the updated documents instead of a rewrite of
+the whole column, and a field keeps up to
+`IndexWriterConfig.DEFAULT_MAX_DOC_VALUES_OVERLAYS` (8) overlays before they
+are folded into one, so more files per field can stay live. To keep the
+full-column rewrite of 10.x, disable the feature when you create the writer:
+
+```java
+IndexWriterConfig config = new IndexWriterConfig(analyzer);
+config.setMaxDocValuesOverlays(0);
+```
+
 ### Filtered HNSW search default threshold (GITHUB#14160)
 
 Filter-optimized HNSW search now runs when 60% or fewer vectors pass the

Trade-offs

No behaviour change. The CHANGES line reaches readers of the release notes; the MIGRATE section reaches people planning the upgrade and gives the opt-out. The MIGRATE wording follows the javadoc (IndexWriterConfig.java:110-114, :335-342) and claims nothing about file counts beyond "more files per field can stay live".

What the checks validated

Scratch worktree of 645d4fe14a20, OpenJDK 25.0.3, 2026-11-01:

  • the notes check prints [11.0.0] lines, "11.0.0 section: 2", "MIGRATE.md: 3", OK, exit 0;
  • ./gradlew :lucene:documentation:changesToHtml :lucene:documentation:markdownToHtml succeeds: the 11.0.0 "Changes in Runtime Behavior" list renders with 2 entries and MIGRATE.html has the new section;
  • ./gradlew :lucene:core:test --tests TestIndexWriterConfig --tests TestIncrementalDocValuesUpdates passes: 24 tests, 0 failures (the diff changes only text, so this only confirms the tree still builds).

CHANGES entry only

The first hunk of the recommended diff (the hunt's original fix).

Trade-offs

Smallest change, but MIGRATE.md is the upgrade guide, and the analogous query-cache flip is in both files.

Make main's default 0, like 10.x

Set DEFAULT_MAX_DOC_VALUES_OVERLAYS = 0 on main.

Trade-offs

Not suggested: it reverses a deliberate decision (#16418, #16648) with a code change to fix a missing sentence.

Leave it to release curation

The status quo.

Trade-offs

The release manager drafts the release notes from CHANGES.txt (releaseWizard.yaml:606-610), so an explicit CHANGES entry is the direct way into them, and branch_11x is already cut.

Downstream note

Search servers and other projects built on Lucene that rely on the default IndexWriterConfig inherit the overlay write path when they move to Lucene 11, and may want to set setMaxDocValuesOverlays explicitly or mention the change in their own upgrade notes.

How it was found

A hunt unit that checked the 10.6.0 CHANGES claims against the release candidate also compared main's notes with main's code. It saw the default 8 under an "Opt-in" note, confirmed the difference with a test that runs the same one-document update with the default config and with the feature off, and traced the note's history in git.

The method in full124 words

Method: non-formal. The oracle is the release notes plus the 10.6 behaviour, checked by reading and a differential test; no model, proof or bounded-exhaustive check took part.

  • The unit's optional main-only part started from a note that main defaults to 8 overlays with no 11.0 CHANGES or MIGRATE entry.
  • The finder compared CHANGES.txt, MIGRATE.md and IndexWriterConfig on main and on the 10.6.0 release-candidate jars, and wrote a public-API JUnit: the same one-document update with a plain new IndexWriterConfig() and with setMaxDocValuesOverlays(0).
  • It traced the provenance of the entry in the full git history; a verifier corrected the introducing commit to ea248114ac4.
  • Because a missing note cannot be unit-tested, a read-only check replaced the JUnit as the minimal repro (this doc's repro).

Prior reports, history and checks

Prior reports

No public report of the missing 11.0 note found (searched 2026-10-28, rechecked 2026-11-01). The default flip itself is public: the #16418 and #16554 PR texts state it, and a downstream issue names it.

Searches5 searches

Related, not reports of the gap: #16418 and #16554 (they state the main/10.x difference), #16648 (the "no CHANGES entry" decision), #16644 (open file handles), #16756 (the 11.0 migrate-guide expansion, no overlay text), #16912 (a similar CHANGES move, merged) and elastic/elasticsearch#163787 (a downstream test-failure issue that names the default). Tracking issue #16937 does not list this item.

What was searched, when, and what turned up
WhereWhenHowFound
Scripted searches, 4 runs2026-10-28198 queries over GitHub issues, PRs and commits, downstream repositories, the dev@, java-user@, issues@ and commits@ lists, the JIRA archive and the webno report of the missing note
GitHub, manual and code search2026-10-2826 issue/PR searches on apache/lucene and downstream projects; 3 code searchesonly the related items above
Open and recent PRs (REST)2026-10-28CHANGES.txt, MIGRATE.md and IndexWriterConfig patches of 72 PRs updated since 2026-10-25 and all 414 open PRsno PR adds the entry
dev@ threads2026-10-28"Lucene 11.0", the 10.6.0 feature-freeze thread and the 10.6.0 RC1 voteno mention of the default or its notes
GitHub search and upstream files2026-11-01setMaxDocValuesOverlays, DEFAULT_MAX_DOC_VALUES_OVERLAYS, "overlay" and "incremental doc-values" since 2026-10-28; the raw CHANGES.txt and MIGRATE.md of main and branch_11xonly #16418 and #16554; the gap is still there on both branches

History

Main lost its 11.0.0 note on 2026-09-01 (ea248114ac4 moved it to 10.6.0) and its last "enabled by default" wording on 2026-10-21 (7cecf795236); no release is affected yet.

Versions tested6 rows

The default itself is deliberate: on since 75eddfaff22 (PR #16418, 2026-08-13, default 16), lowered to 8 by 92d9f2c7faa (PR #16648, 2026-09-08). The before/after boundary rests on a doc-state check over the real git trees, because the JUnit fails on every main commit with the feature (the default has been 16 or 8 there).

Versions and branches executed, with results
Version or commitVerdictResult
main 645d4fe14a20 affecteddefault 8; no 11.0 note; the check exits 1 (the hunt's JUnit fails 2 of 2, -ea and -da)
upstream main f815e679bf6c, branch_11x da3ea39fa597 affectedsame, on the raw upstream files (2026-11-01)
main ea248114ac4 to 7cecf795236^ note misfiledthe 11.0.0 section is silent; the "Enabled by default" text sits under 10.6.0
main 75eddfaff22 to ea248114ac4^ not affectedthe 11.0.0 section says "Enabled by default"
10.6.0 (4ae946e5a9b, released 2026-10-29) not affecteddefault 0, "Opt-in": consistent; the hunt's JUnit passes on jars built from that commit
10.5.2, 9.12.3 and older not affectedno such setting (the JUnit does not compile)

Independent checks

The finder, an independent reproducer, an intended-behaviour devil's advocate and the adjudication call it real, as a minor documentation defect; a cross-model reviewer agreed and the refute lens rated it not real on contract grounds while conceding the gap. A credibility audit kept it.

Checks and verdicts246 words

The cross-model reviews could not run code; a separate run re-ran the finder's JUnit for them (2 of 2 fail). This doc's own runs: the notes check on main and upstream, and the fix validation.

Each independent check and its verdict
CheckVerdictWhat it found
finder reproduced (doc)Notes read against the code; the JUnit fails 2 of 2 on main (-ea, -da), passes on jars built from the 10.6.0 tag (RC1) commit.
cross-model intended lens real, mediumOpenAI GPT-5.6, reading only: default-on is deliberate, but the 11.0 record is missing while the query-cache flip is in CHANGES and MIGRATE; added the MIGRATE precedent and the sorted-numeric path.
Independent reproducer real (doc only)Own JUnit with controls fails 3 of 3 on main and passes on jars built from the RC commit; values read back correctly in every mode.
Cross-model refute lens not real, highOpenAI GPT-5.6, reading only: default-on is intended, entries are optional, 11.0 is unreleased; conceded that neither the 11.0 CHANGES nor MIGRATE records the change.
Intended-behaviour devil's advocate real, minorThe intended case defeats the JUnit framing, not the narrow claim; corrected the introducing commit to ea248114ac4.
adjudication confirmed, doc, minor, medium confidenceThe cross-model review's points go to severity, not reality.
credibility audit confirmedRe-ran the JUnit, re-read code, notes and provenance.
minimal repro no test appliesA missing note cannot be shown by a test; replaced by the read-only check.

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

Finding record

LFV-959, snapshot of 2026-11-06

Registry title
Main (the future 11.0) turns incremental doc-values updates on by default (IndexWriterConfig.DEFAULT_MAX_DOC_VALUES_OVERLAYS = 8; opt-in, 0, in 10.6), but neither the 11.0.0 section of CHANGES.txt nor MIGRATE.md records the change: the only note is the 10.6.0 'Opt-in' entry, because main's 'Enabled by default' note was moved to 10.6.0 and then reworded (documentation defect, unreleased)
Area
release notes (lucene/CHANGES.txt 11.0.0, lucene/MIGRATE.md 10.x -> 11.0) x index / doc-values updates (IndexWriterConfig#DEFAULT_MAX_DOC_VALUES_OVERLAYS, GITHUB#16418, GITHUB#16648)
Priority
Low, rank 1262: The release notes and MIGRATE.md omit a default change on unreleased main that every 11.0 doc-values-update user meets while results stay correct.
Impact class
minor
Impact note
Only main and branch_11x (unreleased 11.0) are affected: an application that upgrades from 10.6 to 11.0, keeps the default IndexWriterConfig and uses the doc-values update APIs (set-only NUMERIC and BINARY updates, and single-valued SORTED_NUMERIC updates per GITHUB#16580) silently moves from whole-column rewrites to up to 8 sparse overlay generations per field (more live files per field, the concern of GITHUB#16644), and no CHANGES or MIGRATE text tells it; search results stay correct, nothing fails, no scale is needed, and the fix is a release-notes entry, not code.
Summary
You upgrade from Lucene 10.6 to 11.0 and use doc-values updates (for example IndexWriter.updateNumericDocValue) with a default IndexWriterConfig; you expect the 11.0 release notes or the migration guide to say so if the default write path changed, as they do for the query cache, which 11.0 turns off by default. Instead main turns incremental doc-values updates on by default (DEFAULT_MAX_DOC_VALUES_OVERLAYS = 8, against 0 in 10.6), so a one-document update writes a small sparse overlay (402 bytes of update files in the repro) instead of rewriting the column (2892 bytes), yet the only CHANGES.txt entry for the feature is the 10.6.0 one, which says 'Opt-in; enable with IndexWriterConfig#setMaxDocValuesOverlays(n)', and MIGRATE.md says nothing. Main did carry an 'Enabled by default' note until it was moved into the 10.6.0 section and then, correctly for 10.6.0, reworded to the release candidate's text.
Introduced
ea248114ac4e3d3a303f3c945c99863d25065882 (main, 'Rename SegmentInfos.VERSION_11_0 to VERSION_10_6', git author Jim Ferenczi, a direct push with no PR): it moved the GITHUB#16418 entry, which then said 'Enabled by default; disable with IndexWriterConfig#setMaxDocValuesOverlays(0)', from the 11.0.0 section to 10.6.0, leaving 11.0.0 with no record (partial); completed by 7cecf795236cfdc40607536db27ae21b923a4366 (main, 'Ensure 10.6.0 changelog in main is consistent with branch_10_6', git author Houston Putman, a direct push), which rewrote that entry to the release candidate's 'Opt-in' text, correct for 10.6.0, and so removed the last 'Enabled by default' wording from main's notes. The default itself is deliberate: on since 75eddfaff22 (PR #16418, default 16), lowered to 8 by 92d9f2c7faa (PR #16648, 'The feature is not yet released, so no CHANGES entry is needed') [read: git show of each commit's CHANGES hunk in the history clone; GitHub lists no PR for ea248114ac4 or 7cecf795236; exec: a doc-state check over the real git trees gives OK at 75eddfaff22 and ea248114ac4^, partial from ea248114ac4 to 7cecf795236^, complete from 7cecf795236 on] (2026-09-01 (author date of ea248114ac4, 2026-09-01T11:35:36+02:00); completed 2026-10-21 (author date of 7cecf795236, 2026-10-21))
First affected version
unreleased (main and branch_11x only; if nothing changes, 11.0.0 would be the first release to ship the default with no note). 10.6.0 (released 2026-10-29; branch_10_6 4ae946e5a9b) is opt-in and documented correctly [exec]; 10.5.2, 9.12.3 and earlier have no setMaxDocValuesOverlays [exec: compile error]
Affected versions
main from ea248114ac4 (2026-09-01) to 7cecf795236^: partial (11.0.0 section silent; the 'Enabled by default' text misfiled under 10.6.0) [exec: doc-state predicate at ea248114ac4, 92d9f2c7faa, 169cbffd12f and 330ee57b167, trees not built]; main from 7cecf795236 (2026-10-21) through a9779ef3c193: complete [exec: the finder's JUnit fails 2 of 2 at 7cecf795236 (-ea), ea57360912e (-ea) and a9779ef3c193 (-ea and -da); the independent reproduction's JUnits fail on a9779ef3c193 (-ea and -da)]; main 645d4fe14a2 (author date 2026-10-28) has the same default and the same notes [exec 2026-10-29: the finder's JUnit fails 2 of 2 with -ea and -da, the independent reproduction's JUnits fail]; branch_11x da3ea39fa597 and upstream main f815e679bf6c (2026-11-01) have the same default and no 11.0 note [exec 2026-11-01: the read-only notes check on their raw upstream files exits 1]. Not affected: main 75eddfaff22 to ea248114ac4^ (its 11.0.0 section said 'Enabled by default') [exec: doc-state predicate]; branch_10_6 4ae946e5a9b (10.6.0 RC1) and the 10.x backport 3a6cd003aaf (default 0, 'Opt-in', consistent) [exec on the RC jars: the finder's JUnit passes 2 of 2 with -ea and -da, the independent reproduction's JUnits pass]; 10.5.2 and 9.12.3 (API absent; the independent reproduction's version-portable byte test passes there, a 1-document update rewrites the whole column) [exec]. All runs on Linux aarch64 with JDK 25.0.3
Status
documented (brief, checks and a per-finding doc exist)
Verification
Confirmed by AI-run checks: an independent repro, a cross-model review that disputed it (the adjudication ruled it real), 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-28): four scripted search runs (198 queries over GitHub issues, PRs and commits, downstream repositories, the dev@, java-user@, issues@ and commits@ lists, the JIRA archive and the web), 26 manual GitHub searches, GitHub code search, the CHANGES.txt, MIGRATE.md and IndexWriterConfig patches of every apache/lucene PR updated since 2026-10-25 (72) and of all 414 open PRs (only the stale #16572 shows the old 10.6.0 entry as unchanged context), every issue updated since 2026-10-25, the bodies, comments and reviews of #16418, #16554, #16648, #16644, #16645 and #16581, and the dev@ 'Lucene 11.0', 10.6.0 feature-freeze and '[VOTE] Release Lucene 10.6.0 RC1' threads. Related, not reports of this gap: #16418 (the feature; 'On main the feature is on by default'), #16554 (10.x backport: 'Unlike on main, it's opt-in on 10.x'), #16648 (16 -> 8: 'The feature is not yet released, so no CHANGES entry'), #16644 (more open file handles with the default), #16756 (the 11.0 migrate-guide expansion, no overlay text), #16912 (a similar CHANGES-placement fix for another entry, merged 2026-10-26: precedent) and downstream elastic/elasticsearch#163787 (opened 2026-10-28: a downstream test failure against the Lucene 11 snapshot that names the 0 -> 8 default as a cause; it does not mention Lucene's CHANGES or MIGRATE). Not fixed: upstream main 645d4fe14a2 has overlay text only in the 10.6.0 section of CHANGES.txt and none in MIGRATE.md. Recheck (2026-10-28): the upstream main head is still 645d4fe14a2, and by title none of the newest PRs (#16913 to #16936) is about the overlay notes.
Lucene commit tested
main 645d4fe14a20 (11.0.0-SNAPSHOT): the read-only notes check before and after the recommended fix in a scratch worktree, with changesToHtml, markdownToHtml and the core suites TestIndexWriterConfig and TestIncrementalDocValuesUpdates (24 tests) on the fixed tree (2026-11-01); the hunt's JUnit with -ea and -da (fails 2 of 2, 2026-10-29). The notes check on the raw upstream files of main f815e679bf6c and branch_11x da3ea39fa597 (2026-11-01). 10.6.0 (4ae946e5a9b): source read; the hunt's JUnit passes on jars built locally from that commit. 10.5.2 and 9.12.3: the setting does not exist.

Lucene and upstream sources

Finding record
  • lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java:110-115 (at a9779ef3c193) (DEFAULT_MAX_DOC_VALUES_OVERLAYS = 8, '0 disables the feature'), :334-346 (setMaxDocValuesOverlays javadoc: 'Enabled by default', @lucene.experimental)
  • lucene/CHANGES.txt:6 (at a9779ef3c193) (Lucene 11.0.0 section), :331-333 (11.0.0 'Changes in Runtime Behavior': only 'GITHUB#14187: The query cache is now disabled by default.'), :446 (10.6.0 section), :491-494 (the only GITHUB#16418 entry: 'Opt-in; enable with IndexWriterConfig#setMaxDocValuesOverlays(n)'), :513-517 (GITHUB#16580, single-valued SORTED_NUMERIC updates reuse the overlay path)
  • lucene/MIGRATE.md:20 (at a9779ef3c193) ('Migration from Lucene 10.x to Lucene 11.0'), :227-236 ('Query caching is now disabled by default', the analogous recorded flip); 0 overlay mentions in the file
  • lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java:357-368 (at a9779ef3c193) (sparseDelta = getMaxDocValuesOverlays() > 0 and no removal: the write path the default selects)
  • branch_10_6 4ae946e5a9b IndexWriterConfig.java:116 (DEFAULT_MAX_DOC_VALUES_OVERLAYS = 0), :343 ('Disabled by default') [read from the git object, the hunt's record and the intended-behaviour check]
  • lucene/CHANGES.txt:341-343 (11.0.0 Changes in Runtime Behavior, only GITHUB#14187), :456 (10.6.0 heading), :501-504 (GITHUB#16418 'Opt-in') on main 645d4fe14a2; MIGRATE.md unchanged
The finding in 30 seconds
  • lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java:110-115, (at 645d4fe14a20) :334-348
  • lucene/core/src/java/org/apache/lucene/index/LiveIndexWriterConfig.java:93-97, (at 645d4fe14a20) :146, :401
  • lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java:358-368 (at 645d4fe14a20)
  • lucene/core/src/java/org/apache/lucene/index/IndexWriter.java:1962, (at 645d4fe14a20) :1996, :2037, :2070
  • lucene/CHANGES.txt:6, (at 645d4fe14a20) :341-343, :456, :501-504, :523-527
  • lucene/MIGRATE.md:20, (at 645d4fe14a20) :227-236, :238-244
  • a Lucene clone releases/lucene/10.6.0 (= 4ae946e5a9b): lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java:116, :343; lucene/CHANGES.txt:51-54 (git show)
Who is affected
  • lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java:110-115 (at 645d4fe14a20)
  • lucene/core/src/java/org/apache/lucene/index/IndexWriter.java:1950-1962, (at 645d4fe14a20) :1996, :2037, :2070
  • lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java:358-368 (at 645d4fe14a20) (set-only updates take the overlay path)
Why it looks unintended
  • lucene/CHANGES.txt:343, (at 645d4fe14a20) :1733-1739, :2394-2403; lucene/MIGRATE.md:227-244
  • lucene/core/src/test/org/apache/lucene/index/TestIncrementalDocValuesUpdates.java:53-61 (at 645d4fe14a20)
  • Lucene main 645d4fe14a20 CONTRIBUTING.md:105-107; dev-tools/scripts/releaseWizard.yaml:600-610
Suggested fix
  • Lucene main 645d4fe14a20 dev-tools/scripts/releaseWizard.yaml:600-610
History
  • a Lucene clone: git for-each-ref refs/tags/releases/lucene/10.6.0 (4ae946e5a9b, tagged 2026-10-29)

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

Repro files

About the diagrams

Made after the fact checks from snapshots of the code, the notes and the executed runs at 645d4fe14a20; the scene asserts every value it draws against them. The PNG is the summary frame.

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.