AdityaTeltia commented on code in PR #16581:
URL: https://github.com/apache/lucene/pull/16581#discussion_r3888730066


##########
lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java:
##########
@@ -367,6 +369,24 @@ private synchronized void handleDVUpdates(
       // back to the dense
       // rewrite. (Skip-indexed fields can't reach here: IndexWriter rejects 
doc-values updates on
       // them.)
+      // A single-valued sorted-numeric field is stored as a numeric column 
and reuses the numeric
+      // update path; a genuinely multi-valued column can't be updated in 
place, so reject it here.
+      // This is the universal choke point for every update path (buffered 
resolve, NRT
+      // tryUpdateDocValue and merge carry-over all funnel through here), and 
the earliest place we
+      // hold a reader to know the column's cardinality. An active overlay 
(existingOverlay != null)
+      // is single-valued by construction, so we only need to check the base 
column.
+      if (type == DocValuesType.SORTED_NUMERIC && existingOverlay == null) {
+        SortedNumericDocValues baseDV = 
reader.getSortedNumericDocValues(field);
+        if (baseDV != null && DocValues.unwrapSingleton(baseDV) == null) {
+          throw new IllegalArgumentException(

Review Comment:
   This rejection happens at write time, but `writeFieldUpdates` only prunes 
`pendingDVUpdates` after `handleDVUpdates` succeeds. The catch block rethrows 
and the pruning loop below it never runs, so the offending 
`DocValuesFieldUpdates` stays in `pendingDVUpdates` and nothing ever removes 
it. Every subsequent commit, NRT reopen, merge, and RAM-triggered flush 
re-enters this loop and throws again. The writer can't commit, refresh, or 
`close()`, and the only recovery is `rollback()`, which discards everything 
since the last commit. Since `handleDVUpdates` iterates all fields under one 
`DocValuesConsumer`, unrelated valid NUMERIC/BINARY updates on the segment are 
blocked permanently too.
   
   `testUpdateOverMultiValuedBaseRejected` encodes this as expected behaviour, 
but from the caller's side it's a data-loss trap: `updateSortedNumericDocValue` 
returned a seqNo successfully, and the failure surfaces later in an unrelated 
operation. In Solr/ES it's reachable from ordinary traffic, since one document 
anywhere in the segment with two values wedges the writer. The check is also 
per-segment, so the same update can be written to segment A and then throw on 
segment B (partial application, no undo), and it can first fire during a 
background merge via `commitMergedDeletesAndUpdates`.
   
   I think validation needs to move to the 
`IndexWriter.updateSortedNumericDocValue` / `updateDocValues` boundary so the 
caller fails fast and nothing is ever buffered. If it has to stay here, the 
minimum is dropping the offending entry from `pendingDVUpdates` before throwing 
so the writer stays usable.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to