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
- Guard every next() with if (iterator.hasNext()) before calling it.
- Use the enhanced for-loop over the DataBuffer (it implements Iterable) which cannot overrun.
- Verify the DataBuffer is non-empty (dataBuffer.getCount() > 0) before iterating and handle the empty case explicitly.
- 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
- Always call hasNext() before next(); never poll next() in an infinite loop.
- Prefer for (T item : dataBuffer) which enforces the bounds for you.
- Handle the empty-DataBuffer (getCount()==0) case explicitly before iterating.
- Close/release the DataBuffer after iteration instead of reusing iterators.
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
- Cannot remove elements from a DataBufferIterator
- Must set attenuationBucketThresholdDb
- Must set attenuationBucketWeights
- Must set daysSinceOnsetToInfectiousness
- Must set reportTypeWhenMissing
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/cad853c4abfdb841.
Report an issue: GitHub.