{"record":{"id":"cad853c4abfdb841","repo":"microg/GmsCore","slug":"cannot-advance-the-iterator-beyond","errorCode":null,"errorMessage":"Cannot advance the iterator beyond ","messagePattern":"Cannot advance the iterator beyond ","errorType":"exception","errorClass":"NoSuchElementException","httpStatus":null,"severity":"error","filePath":"play-services-base/src/main/java/com/google/android/gms/common/data/DataBufferIterator.java","lineNumber":26,"sourceCode":"import androidx.annotation.NonNull;\nimport org.microg.gms.common.Hide;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n@Hide\npublic class DataBufferIterator<T> implements Iterator<T> {\n    protected DataBuffer<T> dataBuffer;\n    protected int position = -1;\n\n    public DataBufferIterator(@NonNull DataBuffer<T> dataBuffer) {\n        this.dataBuffer = dataBuffer;\n    }\n\n    @Override\n    public T next() {\n        if (!hasNext()) {\n            throw new NoSuchElementException(\"Cannot advance the iterator beyond \" + position);\n        }\n        return dataBuffer.get(++position);\n    }\n\n    @Override\n    public void remove() {\n        throw new UnsupportedOperationException(\"Cannot remove elements from a DataBufferIterator\");\n    }\n\n    @Override\n    public boolean hasNext() {\n        return this.position < this.dataBuffer.getCount() - 1;\n    }\n}\n","sourceCodeStart":8,"sourceCodeEnd":41,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-base/src/main/java/com/google/android/gms/common/data/DataBufferIterator.java#L8-L41","documentation":"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.","triggerScenarios":"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.","commonSituations":"while-loop logic that forgets hasNext() checks between calls; iterating a query result that unexpectedly returned zero rows; nested loops sharing one iterator.","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."],"exampleFix":"// before\nwhile (true) {\n    Item item = iterator.next(); // NoSuchElementException at end\n    process(item);\n}\n\n// after\nwhile (iterator.hasNext()) {\n    process(iterator.next());\n}","handlingStrategy":"validation","validationCode":"if (dataBuffer == null || dataBuffer.getCount() == 0) {\n    return; // nothing to iterate\n}","typeGuard":"boolean canAdvance(java.util.Iterator<?> it) {\n    return it.hasNext();\n}","tryCatchPattern":"try {\n    return iterator.next();\n} catch (NoSuchElementException e) {\n    Log.w(TAG, \"Iterator exhausted; check hasNext() before next()\", e);\n    return null;\n}","preventionTips":["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."],"tags":["java","iterator","nosuchelement","databuffer"],"backgroundTag":"index-out-of-bounds","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}