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
- Read all values inside the statement/ResultSet lifetime, before either is closed
- Check rs.isOpen() (or JDBC isClosed()) before touching a set whose state is uncertain
- 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
- Extract all values inside the statement's try block, before resources close
- Check isOpen()/isClosed() before reading from sets held across method boundaries
- Materialize rows into objects first, then close — never keep live ResultSets around
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
- The result set is not open
- ResultSet is not open
- SQLite only supports TYPE_FORWARD_ONLY cursors
- SQLite only supports CONCUR_READ_ONLY cursors
- SQLite only supports closing cursors at commit
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/4e9dad75d1de9086.
Report an issue: GitHub.