{"record":{"id":"6fbf46e14961c081","repo":"tursodatabase/turso","slug":"columnindex-out-of-bound","errorCode":null,"errorMessage":"columnIndex out of bound","messagePattern":"columnIndex out of bound","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/core/TursoResultSet.java","lineNumber":170,"sourceCode":"        return get(i + 1);\n      }\n    }\n\n    throw new SQLException(\"column name \" + columnName + \" not found\");\n  }\n\n  public Object get(int columnIndex) throws SQLException {\n    if (!this.isOpen()) {\n      throw new SQLException(\"ResultSet is not open\");\n    }\n\n    if (this.lastStepResult == null || this.lastStepResult.getResult() == null) {\n      throw new SQLException(\"ResultSet is null\");\n    }\n\n    final Object[] resultSet = this.lastStepResult.getResult();\n    if (columnIndex > resultSet.length || columnIndex < 0) {\n      throw new SQLException(\"columnIndex out of bound\");\n    }\n\n    return resultSet[columnIndex - 1];\n  }\n\n  public String[] getColumnNames() {\n    return this.columnNames;\n  }\n\n  public void setColumnNames(String[] columnNames) {\n    this.columnNames = columnNames;\n  }\n\n  @Override\n  public String toString() {\n    return (\"tursoResultSet{\"\n        + \"statement=\"\n        + statement","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/core/TursoResultSet.java#L152-L188","documentation":"get(int) validates the JDBC 1-based index: it throws for columnIndex greater than the row's column count or negative values. Note an off-by-one hole in the guard: it tests columnIndex < 0, so 0 slips through and reaches resultSet[columnIndex - 1], surfacing as ArrayIndexOutOfBoundsException (index -1) instead of this SQLException — a classic 0-based-index mistake signature.","triggerScenarios":"get(4) on a 3-column result; hardcoded indices left stale after the SELECT list changed; negative indices from computed lookups; get(0) from 0-based habits (produces ArrayIndexOutOfBoundsException, not this message).","commonSituations":"Developers used to 0-based arrays writing rs.get(0); loops starting at 0; SELECT list edited (column removed) while index-based reads unchanged; mixing ordinal and name-based access during refactors.","solutions":["Use 1-based indices — the first column is 1","Derive bounds from rs.getColumnNames().length instead of hardcoding","Prefer get(String) with explicit aliases when the schema may change","Loop with for (int i = 1; i <= rs.getColumnNames().length; i++)"],"exampleFix":"// before\nfor (int i = 0; i < 3; i++) rs.get(i); // get(0) -> ArrayIndexOutOfBounds; get(3) -> out of bound\n\n// after\nString[] cols = rs.getColumnNames();\nfor (int i = 1; i <= cols.length; i++) {\n  Object v = rs.get(i);\n}","handlingStrategy":"validation","validationCode":"int n = rs.getColumnNames().length;\nif (columnIndex >= 1 && columnIndex <= n) {\n  Object v = rs.get(columnIndex);\n}","typeGuard":"static boolean isValidColumnIndex(TursoResultSet rs, int columnIndex) {\n  return columnIndex >= 1 && columnIndex <= rs.getColumnNames().length;\n}","tryCatchPattern":null,"preventionTips":["Treat indices as 1-based — column 0 is invalid and even bypasses the guard into ArrayIndexOutOfBoundsException","Derive the upper bound from rs.getColumnNames().length, never hardcode it","Prefer name-based access (with aliases) so schema changes fail loudly instead of shifting indices"],"tags":["java","jdbc","resultset","columns","off-by-one","bindings"],"backgroundTag":"column-index-out-of-range","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}