{"record":{"id":"7300163b2707789a","repo":"oracle/graal","slug":"empty-iterator-does-not-have-elements","errorCode":null,"errorMessage":"Empty iterator does not have elements","messagePattern":"Empty iterator does not have elements","errorType":"exception","errorClass":"NoSuchElementException","httpStatus":null,"severity":"error","filePath":"sdk/src/org.graalvm.collections/src/org/graalvm/collections/EmptyMap.java","lineNumber":87,"sourceCode":"        public Object getValue() {\n            throw new NoSuchElementException(\"Empty cursor does not have elements\");\n        }\n\n        @Override\n        public Object setValue(Object newValue) {\n            throw new NoSuchElementException(\"Empty cursor does not have elements\");\n        }\n    };\n\n    static final Iterator<Object> EMPTY_ITERATOR = new Iterator<>() {\n        @Override\n        public boolean hasNext() {\n            return false;\n        }\n\n        @Override\n        public Object next() {\n            throw new NoSuchElementException(\"Empty iterator does not have elements\");\n        }\n    };\n\n    static final Iterable<Object> EMPTY_ITERABLE = new Iterable<>() {\n        @Override\n        public Iterator<Object> iterator() {\n            return EMPTY_ITERATOR;\n        }\n    };\n\n    static final EconomicMap<Object, Object> EMPTY_MAP = new EconomicMap<>() {\n        @Override\n        public Object put(Object key, Object value) {\n            EconomicMapImpl.checkNonNull(key);\n            throw new IllegalArgumentException(\"Cannot modify the always-empty map\");\n        }\n\n        @Override","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EmptyMap.java#L69-L105","documentation":"The shared EMPTY_ITERATOR singleton (returned by getKeys() of an empty EconomicMap, iterator() of empty iterables, and EmptySet iteration) throws NoSuchElementException from next() because it yields no elements. hasNext() always returns false; calling next() without checking hasNext() is the classic iteration protocol violation.","triggerScenarios":"Calling next() on the iterator returned by an empty EconomicMap.getKeys().iterator(), EmptySet-style iteration, or any Iterable backed by EmptyMap.EMPTY_ITERABLE, without a preceding true hasNext().","commonSituations":"Hand-written for-loops using a saved iterator after hasNext() returned false; enhanced-for loops are safe, but manual it.next() in while(true) style loops are not; streams/spliterator bridges that call next() eagerly.","solutions":["Always gate next() with hasNext(): while (it.hasNext()) { it.next(); } or use the enhanced-for statement.","Check isEmpty() before obtaining/using the iterator when empties are expected.","Prefer getEntries()/getKeys() with enhanced-for so the protocol cannot be violated."],"exampleFix":"// before\nIterator<K> it = map.getKeys().iterator();\nK k = it.next(); // throws on empty map\n\n// after\nIterator<K> it = map.getKeys().iterator();\nK k = it.hasNext() ? it.next() : null;","handlingStrategy":"validation","validationCode":"Iterator<K> it = map.getKeys().iterator();\nK k = it.hasNext() ? it.next() : null;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pair next() with a preceding hasNext() check.","Prefer enhanced-for loops over manual iterators.","Use isEmpty() to skip empty collections before iterating."],"tags":["graalvm","collections","iteration","iterator"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}