stanfordnlp/CoreNLP · error · IllegalAccessError

Called next without hasNext

Error message

Called next without hasNext

What it means

The merged Pair iterator over two value collections buffers one pending pair. next() checks the ready flag; if next() is called before hasNext() ever primed the buffer (and hasNext() confirms no more pairs), the call is an iterator-protocol violation and throws.

Solutions

  1. Call hasNext() before every next() call
  2. Prefer for-each over the merged Iterable view
  3. Check that both underlying maps/collections are non-empty when at least one pair is expected
  4. Create a fresh iterator after exhaustion instead of reusing it

Example fix

// before
Pair<V1,V2> p = mergedIterator.next();
// after
if (mergedIterator.hasNext()) {
  Pair<V1,V2> p = mergedIterator.next();
}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean has = mergedIterator.hasNext();
if (has) { Pair<V1,V2> p = mergedIterator.next(); }

Type guard

static <A,B> java.util.Optional<Pair<A,B>> nextPairIfPresent(java.util.Iterator<Pair<A,B>> it) {
  return it.hasNext() ? java.util.Optional.of(it.next()) : java.util.Optional.empty();
}

Try / catch

try {
  Pair<V1,V2> p = mergedIterator.next();
} catch (IllegalAccessError e) {
  // called next without hasNext: recover by restarting loop with hasNext guard
  p = null;
}

Prevention

When it happens

Trigger: Calling next() as the first operation on the merged iterator, or calling next() twice in a row without an intervening hasNext().

Common situations: Assuming iterators always have a first element, iterating two maps whose entry sets are empty, or sloppy manual iterator loops over merged collections.

Related errors


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

Appendix: source

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

      Iterator<V1> iterA = iter1.iterator();
      Iterator<V2> iterB = iter2.iterator();

      public Iterator<Pair<V1, V2>> iterator() {
        return new Iterator<Pair<V1,V2>>() {
          boolean ready = false;
          Pair<V1,V2> pending = null;

          public boolean hasNext() {
            if (!ready) {
              pending = nextPair();
              ready = true;
            }
            return pending != null;
          }

          public Pair<V1, V2> next() {
            if (!ready && !hasNext()) {
              throw new IllegalAccessError("Called next without hasNext");
            }
            ready = false;
            return pending;
          }

          public void remove() {
            throw new UnsupportedOperationException("Cannot remove pairs " +
            "from a merged iterator");
          }

          private Pair<V1,V2> nextPair() {
            V1 nextA = null;
            V2 nextB = null;

            while (iterA.hasNext() && iterB.hasNext()) {
              // increment iterators are null
              if (nextA == null) { nextA = iterA.next(); }
              if (nextB == null) { nextB = iterB.next(); }

View on GitHub (pinned to 1b7edd19c4)