{"record":{"id":"9b67eb59e38c36fe","repo":"pentaho/pentaho-kettle","slug":"unable-to-move-resultset-to-position-position","errorCode":null,"errorMessage":"Unable to move resultset to position \" + position","messagePattern":"Unable to move resultset to position \" \\+ position","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/database/Database.java","lineNumber":2945,"sourceCode":"      if ( v != null ) {\n        valueMeta = v;\n        break;\n      }\n    }\n\n    if ( valueMeta != null ) {\n      return valueMeta;\n    }\n\n    throw new KettleDatabaseException( \"Unable to handle database column '\"\n      + name + \"', on column index \" + i + \" : not a handled data type\" );\n  }\n\n  public boolean absolute( ResultSet rs, int position ) throws KettleDatabaseException {\n    try {\n      return rs.absolute( position );\n    } catch ( SQLException e ) {\n      throw new KettleDatabaseException( \"Unable to move resultset to position \" + position, e );\n    }\n  }\n\n  public boolean relative( ResultSet rs, int rows ) throws KettleDatabaseException {\n    try {\n      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  }","sourceCodeStart":2927,"sourceCodeEnd":2963,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/Database.java#L2927-L2963","documentation":"KettleDatabaseException wrapper for ResultSet.absolute(position) failures. absolute() moves the cursor to the given row number and requires a scrollable result set; any SQLException is rethrown with this message.","triggerScenarios":"Calling Database.absolute(rs, position) on a result set that is not scrollable (created with TYPE_FORWARD_ONLY), position beyond row count, or the driver rejecting cursor movement.","commonSituations":"Using absolute() on a default forward-only statement; drivers that don't support scrollable cursors (some MySQL settings); position 0 or negative without proper handling.","solutions":["Create the statement with TYPE_SCROLL_INSENSITIVE/TYPE_SCROLL_SENSITIVE instead of TYPE_FORWARD_ONLY","Check rs.getType() before calling absolute and fall back to re-querying with LIMIT/OFFSET","Validate the position is within the result set size","Update the JDBC driver if scroll support is broken"],"exampleFix":"// before\nStatement st = conn.createStatement();\ndb.absolute(rs, 100);\n// after\nStatement st = conn.createStatement(\n  ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);\nrs = st.executeQuery(sql);\nif (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {\n  db.absolute(rs, 100);\n}","handlingStrategy":"validation","validationCode":"if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {\n  throw new IllegalStateException(\"absolute() requires a scrollable result set\");\n}","typeGuard":"null","tryCatchPattern":"try {\n  db.absolute(rs, pos);\n} catch (KettleDatabaseException e) {\n  // fall back: re-query with LIMIT/OFFSET for the target row\n}","preventionTips":["Always create statements with a scrollable type when navigating","Validate positions against fetched row counts","Prefer ORDER BY + OFFSET re-queries over cursor movement","Confirm driver scrollable-cursor support"],"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"}