{"record":{"id":"b461f809c73af82a","repo":"apache/druid","slug":"no-more-frames-to-produce-call-hasnext-before","errorCode":null,"errorMessage":"No more frames to produce. Call `hasNext()` before calling `next()`","messagePattern":"No more frames to produce\\. Call `hasNext\\(\\)` before calling `next\\(\\)`","errorType":"exception","errorClass":"NoSuchElementException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/scan/ScanResultValueFramesIterable.java","lineNumber":223,"sourceCode":"\n      closer.register(resultSequenceIterator);\n\n      // Makes sure that we run through all the empty scan result values at the beginning and are pointing to a valid\n      // row\n      populateCursor();\n    }\n\n    @Override\n    public boolean hasNext()\n    {\n      return !done();\n    }\n\n    @Override\n    public FrameSignaturePair next()\n    {\n      if (!hasNext()) {\n        throw new NoSuchElementException(\"No more frames to produce. Call `hasNext()` before calling `next()`\");\n      }\n\n      // It would ensure that the cursor and the currentRowSignature is populated properly before we\n      // start all the processing\n      populateCursor();\n      boolean firstRowWritten = false;\n\n      final FrameWriterFactory frameWriterFactory = FrameWriters.makeColumnBasedFrameWriterFactory(\n          memoryAllocatorFactory,\n          currentOutputRowSignature,\n          Collections.emptyList()\n      );\n      final Frame frame;\n      try (final FrameWriter frameWriter = frameWriterFactory.newFrameWriter(\n          new SettableCursorColumnSelectorFactory(() -> currentCursor, currentInputRowSignature))) {\n        while (populateCursor()) { // Do till we don't have any more rows, or the next row isn't compatible with the current row\n          if (!frameWriter.addSelection()) { // Add the cursor's row to the frame, till the frame is full\n            break;","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/scan/ScanResultValueFramesIterable.java#L205-L241","documentation":"This NoSuchElementException is thrown by ScanResultValueFramesIterable's iterator when next() is called after all frames have been exhausted, without first checking hasNext(). The library enforces the standard Java Iterator contract: callers must poll hasNext() before each next() call. It is a caller-side protocol violation, not an internal fault.","triggerScenarios":"Calling iterator.next() repeatedly on a scan-query frame iterator without calling hasNext(); iterating past the last frame in a while(true) loop; using an iterator after draining all frames in custom result-handling code.","commonSituations":"Custom hooks or extension code that consumes scan frames manually instead of a standard for-each loop; porting code that assumed next() would return null at end of stream; wrapping the iterator in an adapter that forgets the hasNext() check.","solutions":["Guard every next() call with if (iterator.hasNext()) or use a for-each loop","Stop iterating as soon as hasNext() returns false; do not call next() again after exhaustion","If buffering frames, track remaining count and avoid extra next() calls"],"exampleFix":"// before\nwhile (true) {\n  FrameSignaturePair frame = iterator.next();\n  process(frame);\n}\n// after\nwhile (iterator.hasNext()) {\n  FrameSignaturePair frame = iterator.next();\n  process(frame);\n}","handlingStrategy":"type-guard","validationCode":"if (it.hasNext()) { FrameSignaturePair f = it.next(); ... }","typeGuard":"boolean safeNext(Iterator<FrameSignaturePair> it) { return it.hasNext(); } // check before any next()","tryCatchPattern":"try { f = it.next(); } catch (NoSuchElementException e) { /* iterator exhausted: stop iterating */ }","preventionTips":["Always use for-each or while(hasNext()) loops over frame iterators","Never call next() twice per element","Treat iterators as one-shot; re-obtain from the iterable if you need to re-iterate"],"tags":["iterator","java","scan-query","protocol-violation"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}