Buggy code:
class Lucene42DocValuesProducer extends DocValuesProducer { private final Map < Integer , Lucene42DocValuesProducer . NumericEntry > numerics ; private final Map < Integer , Lucene42DocValuesProducer . BinaryEntry > binaries ; private final Map < Integer , Lucene42DocValuesProducer . FSTEntry > fsts ; private final IndexInput data ; private final Map < Integer , NumericDocValues > numericInstances = new HashMap < Integer , NumericDocValues > ( ) ; private final Map < Integer , BinaryDocValues > binaryInstances = new HashMap < Integer , BinaryDocValues > ( ) ; private final Map < Integer , FST < Long > > fstInstances = new HashMap < Integer , FST < Long > > ( ) ; private final int maxDoc ; Lucene42DocValuesProducer ( SegmentReadState state , String dataCodec , String dataExtension , String metaCodec , String metaExtension ) throws IOException { } private void readFields ( IndexInput meta , FieldInfos infos ) throws IOException { } @ Override public synchronized NumericDocValues getNumeric ( FieldInfo field ) throws IOException { } private NumericDocValues loadNumeric ( FieldInfo field ) throws IOException { } @ Override public synchronized BinaryDocValues getBinary ( FieldInfo field ) throws IOException { } private BinaryDocValues loadBinary ( FieldInfo field ) throws IOException { } @ Override public SortedDocValues getSorted ( FieldInfo field ) throws IOException { final Lucene42DocValuesProducer . FSTEntry entry = fsts . get ( field . number ) ; FST < Long > instance ; synchronized ( this ) { instance = fstInstances . get ( field . number ) ; if ( instance == null ) { data . seek ( entry . offset ) ; instance = new FST < Long > ( data , PositiveIntOutputs . getSingleton ( true ) ) ; fstInstances . put ( field . number , instance ) ; } } final NumericDocValues docToOrd = getNumeric ( field ) ; final FST < Long > fst = instance ; final BytesReader in = fst . getBytesReader ( ) ; final Arc < Long > firstArc = new Arc < Long > ( ) ; final Arc < Long > scratchArc = new Arc < Long > ( ) ; final IntsRef scratchInts = new IntsRef ( ) ; final BytesRefFSTEnum < Long > fstEnum = new BytesRefFSTEnum < Long > ( fst ) ; return new SortedDocValues ( ) { @ Override public int getOrd ( int docID ) { return ( ( int ) ( docToOrd . get ( docID ) ) ) ; } @ Override public void lookupOrd ( int ord , BytesRef result ) { try { in . setPosition ( 0 ) ; fst . getFirstArc ( firstArc ) ; IntsRef output = Util . getByOutput ( fst , ord , in , firstArc , scratchArc , scratchInts ) ; result . bytes = new byte [ output . length ] ; result . offset = 0 ; result . length = 0 ; Util . toBytesRef ( output , result ) ; } catch ( IOException bogus ) { throw new RuntimeException ( bogus ) ; } } @ Override <START_BUG> public int lookupTerm ( BytesRef key , BytesRef spare ) { <END_BUG> try { InputOutput < Long > o = fstEnum . seekCeil ( key ) ; if ( o == null ) { return ( - ( getValueCount ( ) ) ) - 1 ; } else if ( o . input . equals ( key ) ) { return o . output . intValue ( ) ; } else { return ( ( int ) ( - ( o . output ) ) ) - 1 ; } } catch ( IOException bogus ) { throw new RuntimeException ( bogus ) ; } } @ Override public int getValueCount ( ) { return entry . numOrds ; } } ; } @ Override public void close ( ) throws IOException { } static class NumericEntry { long offset ; boolean tableized ; int packedIntsVersion ; } static class BinaryEntry { long offset ; long numBytes ; int minLength ; int maxLength ; int packedIntsVersion ; int blockSize ; } static class FSTEntry { long offset ; int numOrds ; } }

Fix:
public int lookupTerm ( BytesRef key ) {