{"record":{"id":"ee1fc979c5a5e38c","repo":"stanfordnlp/CoreNLP","slug":"documentiterator-exhausted","errorCode":null,"errorMessage":"DocumentIterator exhausted.","messagePattern":"DocumentIterator exhausted\\.","errorType":"exception","errorClass":"NoSuchElementException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/coref/docreader/CoNLLDocumentReader.java","lineNumber":342,"sourceCode":"    int lineCnt = 0;\n    int docCnt = 0;\n\n    public DocumentIterator(String filename, Options options) throws IOException {\n      this.options = options;\n      this.filename = filename;\n      this.br = IOUtils.readerFromString(filename);\n      nextDoc = readNextDocument();\n    }\n\n    @Override\n    public boolean hasNext() {\n      return nextDoc != null;\n    }\n\n    @Override\n    public CoNLLDocument next() {\n      if (nextDoc == null) {\n        throw new NoSuchElementException(\"DocumentIterator exhausted.\");\n      }\n      CoNLLDocument curDoc = nextDoc;\n      nextDoc = readNextDocument();\n      return curDoc;\n    }\n\n    private static final Pattern starPattern = Pattern.compile(\"\\\\*\");\n\n    private static Tree wordsToParse(List<String[]> sentWords) {\n      StringBuilder sb = new StringBuilder();\n      for (String[] fields:sentWords) {\n        if (sb.length() > 0) {\n          sb.append(' ');\n        }\n\n        String str = fields[FIELD_PARSE_BIT].replace(\"NOPARSE\", \"X\");\n        String tagword = \"(\" + fields[FIELD_POS_TAG] + \" \" + fields[FIELD_WORD] + \")\";\n        // Replace stars","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/coref/docreader/CoNLLDocumentReader.java#L324-L360","documentation":"CoNLLDocumentReader.DocumentIterator.next() implements java.util.Iterator semantics: when the internal lookahead document (nextDoc) is null because all underlying files/lines have been consumed, it throws NoSuchElementException instead of returning null. Callers are expected to check hasNext() before calling next(); this throw signals the iterator was advanced past its end.","triggerScenarios":"Calling next() on the reader's DocumentIterator after hasNext() returned false, or calling next() more times than there are documents without checking hasNext().","commonSituations":"Manual iteration loops over CoNLL corpus files that use a do-while or fixed-count loop instead of while(hasNext()); reusing an exhausted iterator after a first pass; off-by-one when counting documents in the CoNLL-2012 corpus.","solutions":["Guard every next() call with while (it.hasNext()) { ... }","If you need a reusable pass, create a new DocumentIterator from the reader instead of reusing the exhausted one","If collecting all documents, use a for-each loop over the Iterable rather than manual next() calls"],"exampleFix":"// before\nwhile (true) {\n  CoNLLDocument doc = docIter.next(); // throws at end\n  process(doc);\n}\n// after\nwhile (docIter.hasNext()) {\n  CoNLLDocument doc = docIter.next();\n  process(doc);\n}","handlingStrategy":"type-guard","validationCode":"if (docIter.hasNext()) { CoNLLDocument d = docIter.next(); }","typeGuard":"function nextOrNull(Iterator<CoNLLDocument> it) { return it.hasNext() ? it.next() : null; }","tryCatchPattern":"try { doc = docIter.next(); } catch (NoSuchElementException e) { doc = null; // treat as end of iteration }","preventionTips":["Always loop with hasNext() before next()","Never call next() twice for one element","Create a fresh iterator for a second pass over the corpus"],"tags":["java","iterator","nosuch-element","coreference"],"backgroundTag":"empty-result-set","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}