pentaho/pentaho-kettle · error · ArrayIndexOutOfBoundsException

Read beyond last row: " + rownr

Error message

Read beyond last row: " + rownr

What it means

PoiSheet.getRow(int rownr) throws ArrayIndexOutOfBoundsException ('Read beyond last row: <rownr>') when rownr exceeds sheet.getLastRowNum(). Note the asymmetry: a rownr below the first row number returns an empty array rather than throwing, only indices past the last row are rejected.

Solutions

  1. Bound loops with sheet.getRows()/getLastRowNum() instead of a hard-coded count.
  2. Verify your row indices are 0-based; POI and this API both index from 0.
  3. Catch ArrayIndexOutOfBoundsException as end-of-data when doing speculative reads.
  4. Re-read the workbook if the file may have been modified since opening.

Example fix

// before
for (int r = 0; r <= 5000; r++) sheet.getRow(r); // may exceed last row
// after
int last = sheet.getRows();
for (int r = 0; r < last; r++) sheet.getRow(r);
Defensive patterns

Strategy: validation

Validate before calling

if (rownr >= sheet.getFirstRowNum() && rownr <= sheet.getLastRowNum()) { KCell[] row = sheet.getRow(rownr); }

Try / catch

try { KCell[] row = sheet.getRow(rownr); } catch (ArrayIndexOutOfBoundsException e) { row = new KCell[]{}; }

Prevention

When it happens

Trigger: Requesting a row index greater than the POI sheet's last row number — usually from a loop bounded by a configured or hard-coded row count rather than the sheet's real extent.

Common situations: Looping to a fixed end row after the source file shrank; using a 1-based row count where the API expects 0-based indices; previewing a sheet whose data changed between configuration and run.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/4ba0408b9fe98a66. Report an issue: GitHub.

Appendix: source

Thrown at plugins/excel/core/src/main/java/org/pentaho/di/trans/steps/excelinput/poi/PoiSheet.java:38

import org.pentaho.di.core.spreadsheet.KCell;
import org.pentaho.di.core.spreadsheet.KSheet;

public class PoiSheet implements KSheet {
  private Sheet sheet;

  public PoiSheet( Sheet sheet ) {
    this.sheet = sheet;
  }

  public String getName() {
    return sheet.getSheetName();
  }

  public KCell[] getRow( int rownr ) {
    if ( rownr < sheet.getFirstRowNum() ) {
      return new KCell[] {};
    } else if ( rownr > sheet.getLastRowNum() ) {
      throw new ArrayIndexOutOfBoundsException( "Read beyond last row: " + rownr );
    }
    Row row = sheet.getRow( rownr );
    if ( row == null ) { // read an empty row
      return new KCell[] {};
    }
    int cols = row.getLastCellNum();
    if ( cols < 0 ) { // this happens if a row has no cells, POI returns -1 then
      return new KCell[] {};
    }
    PoiCell[] xlsCells = new PoiCell[cols];
    for ( int i = 0; i < cols; i++ ) {
      Cell cell = row.getCell( i );
      if ( cell != null ) {
        xlsCells[i] = new PoiCell( cell );
      }
    }
    return xlsCells;
  }

View on GitHub (pinned to f3058517a1)