tursodatabase/turso · error · SQLException

Index out of bound: {}

Error message

Index out of bound: {}

What it means

getColumnName(int) validates the 1-based column index against the underlying result set (`resultSet.getColumnNames().length`) and throws SQLException("Index out of bound: " + column) when column <= 0 or column > column count. getColumnLabel delegates to this method, so label lookups fail identically. getColumnCount() is implemented and returns the same length, so callers can pre-validate.

Source

Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4ResultSet.java:1312

  @Override
  public int getColumnDisplaySize(int column) throws SQLException {
    return Integer.MAX_VALUE;
  }

  @Override
  public String getColumnLabel(int column) throws SQLException {
    // TODO: should consider "AS" keyword
    return getColumnName(column);
  }

  @Override
  public String getColumnName(int column) throws SQLException {
    if (column > 0 && column <= resultSet.getColumnNames().length) {
      return resultSet.getColumnNames()[column - 1];
    }

    throw new SQLException("Index out of bound: " + column);
  }

  @Override
  public String getSchemaName(int column) throws SQLException {
    throw new UnsupportedOperationException("not implemented");
  }

  @Override
  public int getPrecision(int column) throws SQLException {
    throw new UnsupportedOperationException("not implemented");
  }

  @Override
  public int getScale(int column) throws SQLException {
    throw new UnsupportedOperationException("not implemented");
  }

  @Override

View on GitHub (pinned to 244cde92a7)

Solutions

  1. Use 1-based indexes for all JDBC column access
  2. Loop columns with `for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++)`
  3. Resolve positions via rs.findColumn(name) on the current result set instead of hardcoding them
  4. If the index is external input, validate 1..getColumnCount() before calling

Example fix

// before
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
  String name = rs.getMetaData().getColumnName(i); // throws for i == 0
}

// after
ResultSetMetaData md = rs.getMetaData();
for (int i = 1; i <= md.getColumnCount(); i++) {
  String name = md.getColumnName(i);
}
Defensive patterns

Strategy: validation

Validate before calling

ResultSetMetaData md = rs.getMetaData();
int n = md.getColumnCount();
if (column < 1 || column > n) {
  throw new IllegalArgumentException("column must be in 1.." + n + ", got " + column);
}
String name = md.getColumnName(column);

Try / catch

try {
  String name = rs.getMetaData().getColumnName(column);
} catch (SQLException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Index out of bound")) {
    // bad index: recompute from findColumn or fail with context
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling getColumnName or getColumnLabel with 0 (the classic 0-based array index bug), a negative value, or an index larger than the SELECT's column list, e.g. a hardcoded position left over after the query was rewritten to return fewer columns, or a position taken from a different statement's result set.

Common situations: Porting loops that iterate columns from 0; table renderers and metadata walkers using array indices directly; cached column positions drifting out of sync with an edited SELECT; findColumn fallback code that falls back to positions from another query.

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/26d9400851a02660. Report an issue: GitHub.