tursodatabase/turso · error · SQLException

column name " + columnName + " not found

Error message

column name " + columnName + " not found

What it means

get(String columnName) does a case-sensitive linear scan over the column names returned by the native columns() call and throws when no entry equals the given name exactly. Names are whatever the engine reports for the select list — including aliases and, for bare expressions, the expression text.

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 bad083fafb)

Solutions

  1. Print or inspect rs.getColumnNames() and use the exact reported label
  2. Add explicit AS aliases in the SELECT list and access by those aliases
  3. Fall back to 1-based ordinal access get(i)
  4. For tolerant lookup, resolve the index yourself from getColumnNames() (e.g. case-insensitively) and call get(int)

Example fix

// before
Object v = rs.get("userId"); // actual label is "userid" -> throws

// after
// SELECT id AS userId FROM t
Object v = rs.get("userId"); // alias matches exactly
// or resolve defensively:
String[] cols = rs.getColumnNames();
for (int i = 0; i < cols.length; i++) {
  if (cols[i].equalsIgnoreCase("userId")) { v = rs.get(i + 1); break; }
}
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].equalsIgnoreCase(columnName)) { idx = i; break; }
}
if (idx < 0) {
  throw new IllegalArgumentException(
      "no column " + columnName + " in " + java.util.Arrays.toString(cols));
}
Object v = rs.get(idx + 1);

Type guard

static boolean hasColumn(TursoResultSet rs, String columnName) {
  for (String c : rs.getColumnNames()) {
    if (c.equals(columnName)) return true;
  }
  return false;
}

Prevention

When it happens

Trigger: get("userId") when the label is "userid" or "USERID"; querying SELECT u.name AS user_name but asking for "name"; unaliased expressions (SELECT COUNT(*) reports a synthesized label); accessing a column dropped in a schema change; names with stray whitespace from config files.

Common situations: Joins with aliases where the code uses the original column name; ORMs mapping Java field names (camelCase) onto unaliased SQL columns; schema migrations renaming columns without updating readers; duplicate column names where only the first index matches.

Related errors


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/5c5e81bb33910089. Report an issue: GitHub.