stanfordnlp/CoreNLP · error · IllegalStateException

Called remove() before any elements returned

Error message

Called remove() before any elements returned

What it means

The iterator inside Redwood.RecordHandlerTree throws IllegalStateException("Called remove() before any elements returned") when Iterator.remove() is invoked before next() has returned any element (lastReturned == null). Per the Iterator contract, remove() is only valid after a successful next().

Solutions

  1. Always call next() before remove(): remove() deletes the element last returned by next()
  2. Call remove() at most once per next()
  3. To clear children, iterate with next() and call remove() after each element retrieved
  4. If you only need to empty the tree, use a dedicated clear/removeChild API instead of raw iterator removal

Example fix

// before
Iterator<Redwood.RecordHandlerTree> it = tree.children();
it.remove(); // throws
// after
Iterator<Redwood.RecordHandlerTree> it = tree.children();
while (it.hasNext()) {
  Redwood.RecordHandlerTree t = it.next();
  if (matches(t)) it.remove();
}
Defensive patterns

Strategy: validation

Validate before calling

if (it.hasNext()) {
  var elem = it.next();
  if (shouldRemove(elem)) it.remove();
}

Try / catch

try {
  it.remove();
} catch (IllegalStateException e) {
  log.warn("remove() called before next(): {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling it.remove() on a freshly obtained handler-tree iterator; calling remove() twice in a row without an intervening next(); calling remove() after the last next() threw.

Common situations: Cleanup loops that remove handlers without first advancing the iterator; defensive cleanup code written as `while(it.hasNext()) it.remove();` variants that call remove before next; duplicated remove calls in error paths.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/util/logging/Redwood.java:717

              break;
            } else {
              childIter = childrenIter.next().iterator();
            }
          }
          return !seenHead || (childIter != null && childIter.hasNext());
        }
        // -- Next
        @Override
        public LogRecordHandler next() {
          if(!seenHead){ seenHead = true; return head(); }
          lastReturned = childIter.next();
          return lastReturned;
        }
        // -- Remove
        @Override
        public void remove() {
          if(!seenHead){ throw new IllegalStateException("INTERNAL: this shouldn't happen..."); }
          if(lastReturned == null){ throw new IllegalStateException("Called remove() before any elements returned"); }
          if(childOnPrix != null && lastReturned == childOnPrix.head()){
            childrenIter.remove();
          } else if(childIter != null){
            childIter.remove();
          } else {
            throw new IllegalStateException("INTERNAL: not sure what we're removing");
          }
        }
      };
    }

    private static List<Record> append(List<Record> lst, Record toAppend){
      if(lst == LogRecordHandler.EMPTY){
        lst = new ArrayList<>();
      }
      lst.add(toAppend);
      return lst;
    }

View on GitHub (pinned to 1b7edd19c4)