{"record":{"id":"71a950ba98f2a592","repo":"apache/seatunnel","slug":"no-more-rows-to-read","errorCode":null,"errorMessage":"no more rows to read.","messagePattern":"no more rows to read\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/arrow/reader/ArrowToSeatunnelRowReader.java","lineNumber":128,"sourceCode":"                }\n                convertSeatunnelRow();\n                this.readRowCount += root.getRowCount();\n            }\n            return this;\n        } catch (IOException e) {\n            throw new RuntimeException(e);\n        } finally {\n            close();\n        }\n    }\n\n    public boolean hasNext() {\n        return offsetInRowBatch < readRowCount;\n    }\n\n    public SeaTunnelRow next() {\n        if (!hasNext()) {\n            throw new IllegalStateException(\"no more rows to read.\");\n        }\n        return seatunnelRowBatch.get(offsetInRowBatch++);\n    }\n\n    private void convertSeatunnelRow() {\n        for (FieldVector fieldVector : fieldVectors) {\n            String name = fieldVector.getField().getName();\n            Integer fieldIndex = fieldIndexMap.get(name);\n            Types.MinorType minorType = fieldVector.getMinorType();\n            for (int i = 0; i < seatunnelRowBatch.size(); i++) {\n                // arrow field not in the Seatunnel Schema field, skip it\n                if (fieldIndex != null) {\n                    SeaTunnelDataType<?> seaTunnelDataType = seaTunnelDataTypes[fieldIndex];\n                    Object fieldValue =\n                            convertArrowData(\n                                    readRowCount + i, minorType, fieldVector, seaTunnelDataType);\n                    fieldValue =\n                            convertSeatunnelRowValue(","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/arrow/reader/ArrowToSeatunnelRowReader.java#L110-L146","documentation":"ArrowToSeatunnelRowReader.next() guards on hasNext(); calling next() after all rows of the current row batch are consumed throws IllegalStateException(\"no more rows to read.\"). Callers must check hasNext() before each next() call — it's a strict iterator-contract violation, not a data problem.","triggerScenarios":"Invoking next() when offsetInRowBatch >= readRowCount — i.e. looping past the row count of the loaded Arrow row batch, typically a loop missing a hasNext() check or reading after the batch was exhausted.","commonSituations":"Custom code iterating ArrowSourceReader results without hasNext(); a retry path re-reading rows after exhaustion; off-by-one in a for-loop bound vs. the batch's row count.","solutions":["Wrap the read loop with hasNext(): `while (reader.hasNext()) { row = reader.next(); }`.","If you need more rows, load/advance the next row batch rather than calling next() again on the exhausted one.","Audit retry/re-read logic so a re-read starts from a fresh reader or resets the offset.","Check loop bounds — use hasNext() instead of a hard-coded count that can drift from readRowCount."],"exampleFix":"// before\nfor (int i = 0; i < size; i++) { rows.add(reader.next()); } // size may exceed batch rows\n// after\nwhile (reader.hasNext()) { rows.add(reader.next()); }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Java narrowing: always gate next() on hasNext()\nif (!reader.hasNext()) {\n    return null; // batch exhausted — advance to next batch instead\n}","tryCatchPattern":"try {\n    row = reader.next();\n} catch (IllegalStateException e) {\n    LOG.warn(\"row batch exhausted; loading next batch\");\n    loadNextBatch();\n}","preventionTips":["Always use while(reader.hasNext()) loops instead of index-based loops over row batches.","Never retry next() after exhaustion — load the next batch or create a new reader.","Centralize batch iteration in one utility so the hasNext/next contract is enforced once."],"tags":["arrow","reader","iterator","illegal-state"],"backgroundTag":"index-out-of-bounds","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}