Buggy code:
public class MultiDocValues extends DocValues { private static MultiDocValues . DocValuesPuller DEFAULT_PULLER = new MultiDocValues . DocValuesPuller ( ) ; private static final MultiDocValues . DocValuesPuller NORMS_PULLER = new MultiDocValues . DocValuesPuller ( ) { public DocValues pull ( AtomicReader reader , String field ) throws IOException { } public boolean stopLoadingOnNull ( AtomicReader reader , String field ) { } } ; public static class DocValuesSlice { public static final MultiDocValues . DocValuesSlice [ ] EMPTY_ARRAY = new MultiDocValues . DocValuesSlice [ 0 ] ; final int start ; final int length ; DocValues docValues ; public DocValuesSlice ( DocValues docValues , int start , int length ) { } } private static class DocValuesPuller { public DocValuesPuller ( ) { } public DocValues pull ( AtomicReader reader , String field ) throws IOException { } public boolean stopLoadingOnNull ( AtomicReader reader , String field ) { } } private MultiDocValues . DocValuesSlice [ ] slices ; private int [ ] starts ; private Type type ; private int valueSize ; private MultiDocValues ( MultiDocValues . DocValuesSlice [ ] slices , int [ ] starts , TypePromoter promotedType ) { } public static DocValues getDocValues ( IndexReader r , final String field ) throws IOException { } public static DocValues getNormDocValues ( IndexReader r , final String field ) throws IOException { } private static DocValues getDocValues ( IndexReader reader , final String field , final MultiDocValues . DocValuesPuller puller ) throws IOException { if ( reader instanceof AtomicReader ) { return puller . pull ( ( ( AtomicReader ) ( reader ) ) , field ) ; } assert reader instanceof CompositeReader ; <START_BUG> final List < AtomicReaderContext > leaves = reader . getTopReaderContext ( ) . leaves ( ) ; <END_BUG> switch ( leaves . size ( ) ) { case 0 : return null ; case 1 : return MultiDocValues . getDocValues ( leaves . get ( 0 ) . reader ( ) , field , puller ) ; default : final List < MultiDocValues . DocValuesSlice > slices = new ArrayList < MultiDocValues . DocValuesSlice > ( ) ; TypePromoter promotedType = TypePromoter . getIdentityPromoter ( ) ; for ( final AtomicReaderContext ctx : leaves ) { final AtomicReader r = ctx . reader ( ) ; final DocValues d = puller . pull ( r , field ) ; if ( d != null ) { TypePromoter incoming = TypePromoter . create ( d . getType ( ) , d . getValueSize ( ) ) ; promotedType = promotedType . promote ( incoming ) ; } else if ( puller . stopLoadingOnNull ( r , field ) ) { return null ; } slices . add ( new MultiDocValues . DocValuesSlice ( d , ctx . docBase , r . maxDoc ( ) ) ) ; } if ( promotedType == ( TypePromoter . getIdentityPromoter ( ) ) ) { return null ; } int [ ] starts = new int [ slices . size ( ) ] ; for ( int i = 0 ; i < ( slices . size ( ) ) ; i ++ ) { MultiDocValues . DocValuesSlice slice = slices . get ( i ) ; starts [ i ] = slice . start ; if ( ( slice . docValues ) == null ) { Type promoted = promotedType . type ( ) ; switch ( promoted ) { case BYTES_FIXED_DEREF : case BYTES_FIXED_STRAIGHT : case BYTES_FIXED_SORTED : assert ( promotedType . getValueSize ( ) ) >= 0 ; slice . docValues = new MultiDocValues . EmptyFixedDocValues ( slice . length , promoted , promotedType . getValueSize ( ) ) ; break ; default : slice . docValues = new MultiDocValues . EmptyDocValues ( slice . length , promoted ) ; } } } return new MultiDocValues ( slices . toArray ( new MultiDocValues . DocValuesSlice [ slices . size ( ) ] ) , starts , promotedType ) ; } } @ Override public Source load ( ) throws IOException { } public static class EmptyDocValues extends DocValues { final int maxDoc ; final Source emptySource ; public EmptyDocValues ( int maxDoc , Type type ) { } @ Override public Source load ( ) throws IOException { } @ Override public Type getType ( ) { } @ Override public Source getDirectSource ( ) throws IOException { } } public static class EmptyFixedDocValues extends DocValues { final int maxDoc ; final Source emptyFixedSource ; final int valueSize ; public EmptyFixedDocValues ( int maxDoc , Type type , int valueSize ) { } @ Override public Source load ( ) throws IOException { } @ Override public Type getType ( ) { } @ Override public int getValueSize ( ) { } @ Override public Source getDirectSource ( ) throws IOException { } } private static class MultiSource extends Source { private int numDocs = 0 ; private int start = 0 ; private Source current ; private final int [ ] starts ; private final MultiDocValues . DocValuesSlice [ ] slices ; private boolean direct ; private Object cachedArray ; public MultiSource ( MultiDocValues . DocValuesSlice [ ] slices , int [ ] starts , boolean direct , Type type ) { } public long getInt ( int docID ) { } private final int ensureSource ( int docID ) { } public double getFloat ( int docID ) { } public BytesRef getBytes ( int docID , BytesRef bytesRef ) { } @ Override public SortedSource asSortedSource ( ) { } private int globalNumDocs ( ) { } private int [ ] docBases ( ) { } public boolean hasArray ( ) { } @ Override public Object getArray ( ) { } } private static final class RecordingBytesRefConsumer implements SortedBytesMergeUtils . BytesRefConsumer { private static final int PAGED_BYTES_BITS = 15 ; final PagedBytes pagedBytes = new PagedBytes ( MultiDocValues . RecordingBytesRefConsumer . PAGED_BYTES_BITS ) ; long [ ] ordToOffset ;

Fix:
final List < AtomicReaderContext > leaves = reader . leaves ( ) ;