stanfordnlp/CoreNLP · error · IllegalStateException

Didn't have next

Error message

Didn't have next

What it means

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.

Solutions

  1. Guard each next() with hasNext() or use for-each
  2. Obtain a new iterator once exhausted
  3. Log/inspect the underlying iterables if you expected more elements
  4. Avoid caching iterators across loop boundaries

Example fix

// before
V v = concatIterator.next();
// after
if (concatIterator.hasNext()) {
  V v = concatIterator.next();
}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean has = it.hasNext();
if (has) { V v = it.next(); }

Type guard

static <V> java.util.Optional<V> nextIfPresent(java.util.Iterator<V> it) {
  return it.hasNext() ? java.util.Optional.of(it.next()) : java.util.Optional.empty();
}

Try / catch

try {
  V v = it.next();
} catch (IllegalStateException e) {
  if ("Didn't have next".equals(e.getMessage())) {
    v = null; // exhausted
  } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: Manual while loops that forget to re-check hasNext(), do/while usage, iterating concatenated empty iterables, or reusing an exhausted iterator.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/f8052ed77da8b090. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/util/Iterables.java:554

              public boolean hasNext() {
                // get next if we need to and one is available
                if (next == null && it.hasNext()) {
                  next = it.next();
                }

                // if next and last both have values, compare them
                if (last != null && next != null) {
                  return comparator.compare(last, next) == 0;
                }

                // one of them was not null - have more if it was next
                return next != null;
              }

              public V next() {
                if (!hasNext()) {
                  throw new IllegalStateException("Didn't have next");
                }
                V rv = next;
                last = next;
                next = null;
                return rv;
              }

              public void remove() {
                throw new UnsupportedOperationException();
              }
            };
          }

          public void remove() {
            throw new UnsupportedOperationException();
          }
        };
      }

View on GitHub (pinned to 1b7edd19c4)