{"record":{"id":"f8052ed77da8b090","repo":"stanfordnlp/CoreNLP","slug":"didn-t-have-next","errorCode":null,"errorMessage":"Didn't have next","messagePattern":"Didn't have next","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/util/Iterables.java","lineNumber":554,"sourceCode":"\n              public boolean hasNext() {\n                // get next if we need to and one is available\n                if (next == null && it.hasNext()) {\n                  next = it.next();\n                }\n\n                // if next and last both have values, compare them\n                if (last != null && next != null) {\n                  return comparator.compare(last, next) == 0;\n                }\n\n                // one of them was not null - have more if it was next\n                return next != null;\n              }\n\n              public V next() {\n                if (!hasNext()) {\n                  throw new IllegalStateException(\"Didn't have next\");\n                }\n                V rv = next;\n                last = next;\n                next = null;\n                return rv;\n              }\n\n              public void remove() {\n                throw new UnsupportedOperationException();\n              }\n            };\n          }\n\n          public void remove() {\n            throw new UnsupportedOperationException();\n          }\n        };\n      }","sourceCodeStart":536,"sourceCodeEnd":572,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/util/Iterables.java#L536-L572","documentation":"A filtered/concatenated iterator in Iterables keeps a one-element lookahead; next() re-checks hasNext() and throws IllegalStateException if there is no buffered element. This protects against protocol misuse where next() is called on an exhausted iterator.","triggerScenarios":"Calling next() after the underlying concatenation/filter is exhausted, or calling next() twice without hasNext() between calls so the single cached element was already consumed.","commonSituations":"Manual while loops that forget to re-check hasNext(), do/while usage, iterating concatenated empty iterables, or reusing an exhausted iterator.","solutions":["Guard each next() with hasNext() or use for-each","Obtain a new iterator once exhausted","Log/inspect the underlying iterables if you expected more elements","Avoid caching iterators across loop boundaries"],"exampleFix":"// before\nV v = concatIterator.next();\n// after\nif (concatIterator.hasNext()) {\n  V v = concatIterator.next();\n}","handlingStrategy":"type-guard","validationCode":"boolean has = it.hasNext();\nif (has) { V v = it.next(); }","typeGuard":"static <V> java.util.Optional<V> nextIfPresent(java.util.Iterator<V> it) {\n  return it.hasNext() ? java.util.Optional.of(it.next()) : java.util.Optional.empty();\n}","tryCatchPattern":"try {\n  V v = it.next();\n} catch (IllegalStateException e) {\n  if (\"Didn't have next\".equals(e.getMessage())) {\n    v = null; // exhausted\n  } else { throw e; }\n}","preventionTips":["Use for-each or hasNext()-guarded while loops","Get a fresh iterator after exhaustion","Avoid do/while patterns that call next() unconditionally","Don't cache iterators across scopes"],"tags":["iterator","java-collections","misuse"],"backgroundTag":"iterator-next-without-hasnext","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}