dweiss commented on issue #15974:
URL: https://github.com/apache/lucene/issues/15974#issuecomment-4294139668

   I asked claude and it came up with a very plausible cause of this failure -
   ```
     The bug is an off-by-one error in SimpleTextDocValuesReader.getSkipper() 
exposed by the new SkipBlockRangeIterator.                                      
              
      
     The SimpleText skipper bug                                                 
                                                                                
            
                                                               
     In SimpleTextDocValuesReader.java:919, maxDocID(int level) returned maxDoc 
(the exclusive upper bound) instead of maxDoc - 1 (the last valid doc ID, 
inclusive):       
                                                               
     @Override                                                                  
                                                                                
            
     public int maxDocID(int level) {                          
       ...
       return maxDoc;  // BUG: valid doc IDs are 0..maxDoc-1, so max is maxDoc-1
     }
   
     Per the DocValuesSkipper contract: "Return the maximum doc ID of the 
interval on the given level, inclusive." The maximum valid doc ID in any 
segment is maxDoc - 1.   
      
     Why the old code survived                                                  
                                                                                
            
                                                               
     The old code in DocValuesRangeIterator used maxDocID(0) as a tracked upTo 
boundary with a strict > comparison:                                            
             
      
     this.upTo = skipper.maxDocID(0);  // = maxDoc (wrong, but harmless)        
                                                                                
            
     ...                                                       
     if (target > upTo) {              // target > maxDoc — never triggered for 
valid doc IDs!
                                                                                
                                                                                
            
     Because target > maxDoc is never true for valid doc IDs (0 to maxDoc-1), 
the skipper was simply never re-advanced for SimpleText. It also used 
SortedNumericDocValues  
     as its approximation, which itself never returns maxDoc as a doc ID.       
                                                                                
            
                                                                                
                                                                                
            
     How the PR triggers the bug                               
   
     SkipBlockRangeIterator (introduced in e56d5fa) correctly interprets 
maxDocID(0) as inclusive, using:                                                
                   
      
     if (target <= skipper.maxDocID(0)) {   // target <= maxDoc — TRUE for 
target=maxDoc!                                                                  
                 
         if (doc > -1) {                                       
             return doc = target;           // returns maxDoc as a doc ID!
         }                                                                      
                                                                                
            
     }
                                                                                
                                                                                
            
     When iterating docs in the last block of a SimpleText segment, nextDoc() 
on the last valid doc (maxDoc - 1) calls advance(maxDoc). The condition maxDoc 
<= maxDoc is   
     true, so the iterator returns doc = maxDoc. Then matches() calls 
values.advanceExact(maxDoc), which seeks past the end of the data file in 
SimpleTextDocValuesReader,
     and the assertion StringHelper.startsWith(scratch.get(), LENGTH) at line 
468 fails.                                                                      
              
                                                               
     The fix
   
     SimpleTextDocValuesReader.java:919 — return maxDoc - 1 instead of maxDoc:
   
     return maxDoc - 1;  // was: return maxDoc
                                                                                
                                                                                
            
     The SkipBlockRangeIterator logic itself is correct per the contract. 
SimpleTextDocValuesReader.getSkipper() had a latent off-by-one that the new 
code tripped over.    
   ```
   
   I'll wait for somebody more knowledgeable with those iterators to confirm 
but it does look like #15954 uncovered an existing bug in the codec.


-- 
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