tursodatabase/turso · error · SQLException

ResultSet closed

Error message

ResultSet closed

What it means

TursoResultSet.checkOpen() is the shared guard for result-set operations: it throws 'ResultSet closed' whenever open is false. The set is closed by close(), by statement.close() (which delegates to resultSet.close()), by reset() replacing it, or by next() after an invalid step state.

Source

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

  /** Gets the current row number (0-based, 0 means before first row). */
  public int getRow() {
    return row;
  }

  /**
   * Checks the status of the result set.
   *
   * @return true if it's ready to iterate over the result set; false otherwise.
   */
  public boolean isOpen() {
    return open;
  }

  /** @throws SQLException if not {@link #open} */
  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");
  }

View on GitHub (pinned to bad083fafb)

Solutions

  1. Read all values inside the statement/ResultSet lifetime, before either is closed
  2. Check rs.isOpen() (or JDBC isClosed()) before touching a set whose state is uncertain
  3. Copy needed values into POJOs/lists while iterating, then close

Example fix

// before
try (Statement st = conn.createStatement()) {
  ResultSet rs = st.executeQuery(q);
  rs.close();
  return rs.get(1); // throws: ResultSet closed
}

// after
try (Statement st = conn.createStatement()) {
  ResultSet rs = st.executeQuery(q);
  return rs.next() ? rs.get(1) : null;
}
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

try {
  return rs.get(1);
} catch (SQLException e) {
  if ("ResultSet closed".equals(e.getMessage())) {
    return null; // or re-execute the query for a fresh set
  }
  throw e;
}

Prevention

When it happens

Trigger: Any guarded read/metadata operation on a ResultSet after rs.close(), after the owning statement was closed, or after a prior step error flipped open to false.

Common situations: Extracting row values in a helper method called after the statement's try-with-resources block exited; finally-block logging of the last row; frameworks closing statements eagerly before materializing results.

Related errors


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