{"record":{"id":"a00b4703ea7aec26","repo":"pentaho/pentaho-kettle","slug":"unable-to-move-resultset-to-the-first-position","errorCode":null,"errorMessage":"Unable to move resultset to the first position","messagePattern":"Unable to move resultset to the first position","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/database/Database.java","lineNumber":2969,"sourceCode":"      return rs.relative( rows );\n    } catch ( SQLException e ) {\n      throw new KettleDatabaseException( \"Unable to move the resultset forward \" + rows + \" rows\", e );\n    }\n  }\n\n  public void afterLast( ResultSet rs ) throws KettleDatabaseException {\n    try {\n      rs.afterLast();\n    } catch ( SQLException e ) {\n      throw new KettleDatabaseException( \"Unable to move resultset to after the last position\", e );\n    }\n  }\n\n  public void first( ResultSet rs ) throws KettleDatabaseException {\n    try {\n      rs.first();\n    } catch ( SQLException e ) {\n      throw new KettleDatabaseException( \"Unable to move resultset to the first position\", e );\n    }\n  }\n\n  /**\n   * Get a row from the resultset. Do not use lazy conversion\n   *\n   * @param rs The resultset to get the row from\n   * @return one row or null if no row was found on the resultset or if an error occurred.\n   */\n  public Object[] getRow( ResultSet rs ) throws KettleDatabaseException {\n    return getRow( rs, false );\n  }\n\n  /**\n   * Get a row from the resultset.\n   *\n   * @param rs             The resultset to get the row from\n   * @param lazyConversion set to true if strings need to have lazy conversion enabled","sourceCodeStart":2951,"sourceCodeEnd":2987,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/Database.java#L2951-L2987","documentation":"Wrapper error from Database.first(): the JDBC ResultSet.first() call threw an SQLException (e.g. the result set is TYPE_FORWARD_ONLY, already closed, or the driver does not support cursor positioning). The original SQLException is chained as the cause.","triggerScenarios":"Calling Database.first(rs) on a forward-only result set, a closed result set, or with a driver that doesn't implement first().","commonSituations":"Resetting iteration to the beginning on a default statement; driver limitations (e.g. some streaming configurations force forward-only); result set closed after connection issues.","solutions":["Create the Statement with TYPE_SCROLL_INSENSITIVE (note: this may buffer results in memory)","Re-execute the query instead of rewinding a forward-only result set","Check rs.getType() before calling first()","Avoid streaming mode settings that force TYPE_FORWARD_ONLY"],"exampleFix":"// before\nStatement st = conn.createStatement();\ndb.first(rs);\n// after\nStatement st = conn.createStatement(\n  ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);\nrs = st.executeQuery(sql);\ndb.first(rs);","handlingStrategy":"validation","validationCode":"if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {\n  throw new IllegalStateException(\"first() needs a scrollable result set; re-execute instead\");\n}","typeGuard":"null","tryCatchPattern":"try {\n  db.first(rs);\n} catch (KettleDatabaseException e) {\n  // fallback: re-execute the query for a fresh cursor\n}","preventionTips":["Create statements with scrollable type before rewinding","Re-execute queries instead of rewinding forward-only sets","Disable streaming modes that force TYPE_FORWARD_ONLY","Cache first-row results instead of re-navigating"],"tags":["jdbc","resultset","cursor"],"backgroundTag":"unsupported-operation","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}