tursodatabase/turso · error · SQLException

ResultSet is not open

Error message

ResultSet is not open

What it means

get(int columnIndex) starts with an isOpen() check and throws this message ('ResultSet is not open' — a different string from checkOpen()'s 'ResultSet closed', which makes message-based matching brittle). The set is closed by close(), statement close/reset, or a prior invalid step.

Source

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

  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];
  }

  public String[] getColumnNames() {
    return this.columnNames;
  }

View on GitHub (pinned to bad083fafb)

Solutions

  1. Read column values before closing the ResultSet or its statement
  2. Check rs.isOpen() before optional reads
  3. If matching this error in catch blocks, match both message variants ('ResultSet is not open' and 'ResultSet closed')

Example fix

// before
ResultSet rs = st.getResultSet();
st.close();
Object v = rs.get(1); // throws: ResultSet is not open

// after
ResultSet rs = st.getResultSet();
Object v = rs.next() ? rs.get(1) : null;
st.close();
Defensive patterns

Strategy: validation

Validate before calling

if (rs.isOpen()) {
  Object v = rs.get(columnIndex);
}

Try / catch

try {
  return rs.get(columnIndex);
} catch (SQLException e) {
  String m = e.getMessage();
  if ("ResultSet is not open".equals(m) || "ResultSet closed".equals(m)) {
    return null; // set closed underneath — re-execute if the data is required
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling get(int) after rs.close(); after the owning TursoStatement was closed; on the stale ResultSet after TursoStatement.reset(); after a step error set open = false.

Common situations: Deferred materialization patterns that read columns after the statement scope ended; retry loops that re-read from an already-closed set; helper getters invoked from finally blocks.

Related errors


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