microg/GmsCore · error · NoSuchElementException

Cannot advance the iterator beyond

Error message

Cannot advance the iterator beyond 

What it means

DataBufferIterator.next() throws NoSuchElementException('Cannot advance the iterator beyond ' + position) when hasNext() is false, i.e. the iterator is already at the last element (position >= dataBuffer.getCount() - 1). It is the standard Iterator contract enforcement for DataBuffer-backed iteration.

Source

Thrown at play-services-base/src/main/java/com/google/android/gms/common/data/DataBufferIterator.java:26

import androidx.annotation.NonNull;
import org.microg.gms.common.Hide;

import java.util.Iterator;
import java.util.NoSuchElementException;

@Hide
public class DataBufferIterator<T> implements Iterator<T> {
    protected DataBuffer<T> dataBuffer;
    protected int position = -1;

    public DataBufferIterator(@NonNull DataBuffer<T> dataBuffer) {
        this.dataBuffer = dataBuffer;
    }

    @Override
    public T next() {
        if (!hasNext()) {
            throw new NoSuchElementException("Cannot advance the iterator beyond " + position);
        }
        return dataBuffer.get(++position);
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("Cannot remove elements from a DataBufferIterator");
    }

    @Override
    public boolean hasNext() {
        return this.position < this.dataBuffer.getCount() - 1;
    }
}

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Guard every next() with if (iterator.hasNext()) before calling it.
  2. Use the enhanced for-loop over the DataBuffer (it implements Iterable) which cannot overrun.
  3. Verify the DataBuffer is non-empty (dataBuffer.getCount() > 0) before iterating and handle the empty case explicitly.
  4. Release/close the DataBuffer and re-query if a second pass is needed; do not rewind the exhausted iterator.

Example fix

// before
while (true) {
    Item item = iterator.next(); // NoSuchElementException at end
    process(item);
}

// after
while (iterator.hasNext()) {
    process(iterator.next());
}
Defensive patterns

Strategy: validation

Validate before calling

if (dataBuffer == null || dataBuffer.getCount() == 0) {
    return; // nothing to iterate
}

Type guard

boolean canAdvance(java.util.Iterator<?> it) {
    return it.hasNext();
}

Try / catch

try {
    return iterator.next();
} catch (NoSuchElementException e) {
    Log.w(TAG, "Iterator exhausted; check hasNext() before next()", e);
    return null;
}

Prevention

When it happens

Trigger: Calling next() after the loop has consumed all elements; calling next() on an empty DataBuffer (getCount() == 0); manual next() calls without checking hasNext(); reusing an exhausted iterator for a second pass.

Common situations: while-loop logic that forgets hasNext() checks between calls; iterating a query result that unexpectedly returned zero rows; nested loops sharing one iterator.

Related errors


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/cad853c4abfdb841. Report an issue: GitHub.