tursodatabase/turso · error · java.sql.SQLException

column name not found

Error message

column name {columnName} not found

What it means

get(String columnName) performs a linear scan of the columnNames array using exact, case-sensitive equals(); if no element matches the argument it throws. There is no case-insensitive fallback and no metadata lookup, so the argument must match the SQL-produced name byte for byte — quoted identifiers keep their case and any whitespace.

Solutions

  1. Inspect rs.getColumnNames() and use the exact element returned
  2. Make both sides agree explicitly: alias in SQL (SELECT x AS name) and use that alias in code
  3. Resolve the index yourself case-insensitively from getColumnNames(), then call get(int)
  4. Switch to positional get(int) when column names are unstable

Example fix

// before
Object v = rs.get("UserName"); // column is 'username' -> throws

// after
String[] cols = rs.getColumnNames();
int idx = -1;
for (int i = 0; i < cols.length; i++) {
  if (cols[i].equalsIgnoreCase("UserName")) { idx = i + 1; break; }
}
if (idx == -1) throw new IllegalArgumentException("no column 'UserName' in " + java.util.Arrays.toString(cols));
Object v = rs.get(idx);
Defensive patterns

Strategy: validation

Validate before calling

String[] cols = rs.getColumnNames();
int idx = -1;
for (int i = 0; i < cols.length; i++) {
  if (cols[i].equals(wanted) || cols[i].equalsIgnoreCase(wanted)) { idx = i + 1; break; }
}
if (idx == -1) {
  throw new IllegalArgumentException(
      "no column '" + wanted + "' in " + Arrays.toString(cols));
}
Object v = rs.get(idx);

Try / catch

try {
  return rs.get("username");
} catch (SQLException e) {
  throw new IllegalArgumentException(
      "unknown column; available: " + Arrays.toString(rs.getColumnNames()), e);
}

Prevention

When it happens

Trigger: Requesting 'Name' when the query yields 'name'; using the table's column name when the SELECT list aliases it (SELECT x AS y); asking for a column not present in the SELECT list; requesting the table-qualified 't.id' when the result name is just 'id'.

Common situations: SELECT * with case differences between schema and reader constants; expression columns with engine-generated names; refactors renaming columns while reader code lags; whitespace in config-driven column names.

Related errors


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

Appendix: source

Thrown at bindings/java/src/main/java/tech/turso/core/TursoResultSet.java:156

  public void checkOpen() throws SQLException {
    if (!open) {
      throw new SQLException("ResultSet closed");
    }
  }

  public void close() throws SQLException {
    this.open = false;
  }

  public Object get(String columnName) throws SQLException {
    final int columnsLength = this.columnNames.length;
    for (int i = 0; i < columnsLength; i++) {
      if (this.columnNames[i].equals(columnName)) {
        return get(i + 1);
      }
    }

    throw new SQLException("column name " + columnName + " not found");
  }

  public Object get(int columnIndex) throws SQLException {
    if (!this.isOpen()) {
      throw new SQLException("ResultSet is not open");
    }

    if (this.lastStepResult == null || this.lastStepResult.getResult() == null) {
      throw new SQLException("ResultSet is null");
    }

    final Object[] resultSet = this.lastStepResult.getResult();
    if (columnIndex > resultSet.length || columnIndex < 0) {
      throw new SQLException("columnIndex out of bound");
    }

    return resultSet[columnIndex - 1];
  }

View on GitHub (pinned to 244cde92a7)