Buggy code:
@ SuppressCodecs ( { "Direct" , "Memory" } ) public class TestBagOfPositions extends LuceneTestCase { public void test ( ) throws Exception { List < String > postingsList = new ArrayList < > ( ) ; int numTerms = atLeast ( 300 ) ; final int maxTermsPerDoc = TestUtil . nextInt ( random ( ) , 10 , 20 ) ; boolean isSimpleText = "SimpleText" . equals ( TestUtil . getPostingsFormat ( "field" ) ) ; IndexWriterConfig iwc = newIndexWriterConfig ( random ( ) , TEST_VERSION_CURRENT , new org . apache . lucene . analysis . MockAnalyzer ( random ( ) ) ) ; if ( ( isSimpleText || ( ( iwc . getMergePolicy ( ) ) instanceof MockRandomMergePolicy ) ) && ( ( TEST_NIGHTLY ) || ( ( RANDOM_MULTIPLIER ) > 1 ) ) ) { numTerms //= 2 ; } if ( VERBOSE ) { System . out . println ( ( "maxTermsPerDoc=" + maxTermsPerDoc ) ) ; System . out . println ( ( "numTerms=" + numTerms ) ) ; } for ( int i = 0 ; i < numTerms ; i ++ ) { String term = Integer . toString ( i ) ; for ( int j = 0 ; j < i ; j ++ ) { postingsList . add ( term ) ; } } Collections . shuffle ( postingsList , random ( ) ) ; final ConcurrentLinkedQueue < String > postings = new ConcurrentLinkedQueue < > ( postingsList ) ; Directory dir = newFSDirectory ( createTempDir ( "bagofpositions" ) ) ; final RandomIndexWriter iw = new RandomIndexWriter ( random ( ) , dir , iwc ) ; int threadCount = TestUtil . nextInt ( random ( ) , 1 , 5 ) ; if ( VERBOSE ) { System . out . println ( ( "config:<seq2seq4repair_space>" + ( iw . w . getConfig ( ) ) ) ) ; System . out . println ( ( "threadCount=" + threadCount ) ) ; } Field prototype = newTextField ( "field" , "" , NO ) ; FieldType fieldType = new FieldType ( prototype . fieldType ( ) ) ; if ( random ( ) . nextBoolean ( ) ) { fieldType . setOmitNorms ( true ) ; } int options = random ( ) . nextInt ( 3 ) ; if ( options == 0 ) { fieldType . setIndexOptions ( DOCS_AND_FREQS ) ; fieldType . setStoreTermVectors ( true ) ; } else if ( options == 1 ) { fieldType . setIndexOptions ( DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS ) ; } Thread [ ] threads = new Thread [ threadCount ] ; final CountDownLatch startingGun = new CountDownLatch ( 1 ) ; for ( int threadID = 0 ; threadID < threadCount ; threadID ++ ) { final Random threadRandom = new Random ( random ( ) . nextLong ( ) ) ; final Document document = new Document ( ) ; final Field field = new Field ( "field" , "" , fieldType ) ; document . add ( field ) ; threads [ threadID ] = new Thread ( ) { @ Override public void run ( ) { try { startingGun . await ( ) ; while ( ! ( postings . isEmpty ( ) ) ) { StringBuilder text = new StringBuilder ( ) ; int numTerms = threadRandom . nextInt ( maxTermsPerDoc ) ; for ( int i = 0 ; i < numTerms ; i ++ ) { String token = postings . poll ( ) ; if ( token == null ) { break ; } text . append ( '<seq2seq4repair_space>' ) ; text . append ( token ) ; } field . setStringValue ( text . toString ( ) ) ; iw . addDocument ( document ) ; } } catch ( Exception e ) { throw new RuntimeException ( e ) ; } } } ; threads [ threadID ] . start ( ) ; } startingGun . countDown ( ) ; for ( Thread t : threads ) { t . join ( ) ; } iw . forceMerge ( 1 ) ; DirectoryReader ir = iw . getReader ( ) ; assertEquals ( 1 , ir . leaves ( ) . size ( ) ) ; AtomicReader air = ir . leaves ( ) . get ( 0 ) . reader ( ) ; Terms terms = air . terms ( "field" ) ; assertEquals ( ( numTerms - 1 ) , terms . size ( ) ) ; TermsEnum termsEnum = terms . iterator ( null ) ; BytesRef term ; while ( ( term = termsEnum . next ( ) ) != null ) { int value = Integer . parseInt ( term . utf8ToString ( ) ) ; assertEquals ( value , termsEnum . totalTermFreq ( ) ) ; } ir . close ( ) ; <START_BUG> iw . close ( ) ; <END_BUG> dir . close ( ) ; } }

Fix:
iw . shutdown ( ) ;