tursodatabase/turso · error · SQLException
The resultSet is not open
Error message
The resultSet is not open
What it means
TursoResultSet.next() throws when open is false. A set starts open (constructed via TursoResultSet.of), and becomes closed by close(), by statement.close() (which closes its shared ResultSet), by reset(), or by next() itself when a step returned an invalid state (it sets open = false before throwing).
Source
Thrown at bindings/java/src/main/java/tech/turso/core/TursoResultSet.java:74
while (next()) {}
}
/**
* Moves the cursor forward one row from its current position. A {@link TursoResultSet} cursor is
* initially positioned before the first fow; the first call to the method <code>next</code> makes
* the first row the current row; the second call makes the second row the current row, and so on.
* When a call to the <code>next</code> method returns <code>false</code>, the cursor is
* positioned after the last row.
*
* <p>Note that turso only supports <code>ResultSet.TYPE_FORWARD_ONLY</code>, which means that the
* cursor can only move forward.
*
* @return true if the new current row is valid; false if there are no more rows
* @throws SQLException if a database access error occurs
*/
public boolean next() throws SQLException {
if (!open) {
throw new SQLException("The resultSet is not open");
}
if (isEmptyResultSet || pastLastRow) {
return false; // completed ResultSet
}
if (maxRows != 0 && row == maxRows) {
return false;
}
lastStepResult = this.statement.step();
log.debug("lastStepResult: {}", lastStepResult);
if (lastStepResult.isRow()) {
row++;
}
if (lastStepResult.isInInvalidState()) {
open = false;View on GitHub (pinned to bad083fafb)
Solutions
- Iterate exactly once with while (rs.next()) { ... } and never call next() after an exception
- Check rs.isOpen() before any optional extra next() call
- After a step error, re-prepare/re-execute instead of continuing to step the dead set
Example fix
// before
try { while (rs.next()) { process(rs); } }
catch (SQLException e) { /* ... */ }
finally { while (rs.next()) {} } // throws: The resultSet is not open
// after
try {
while (rs.isOpen() && rs.next()) { process(rs); }
} catch (SQLException e) {
// rs is closed now — do not step it again
} Defensive patterns
Strategy: try-catch
Validate before calling
while (rs.isOpen() && rs.next()) {
process(rs);
} Try / catch
try {
while (rs.next()) {
process(rs);
}
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("resultSet is not open")) {
// set was closed underneath — stop iterating, do not call next() again
} else {
throw e;
}
} Prevention
- Iterate each ResultSet exactly once, inside the statement's lifetime
- Never call next() in finally blocks after the body may have thrown
- Scope try-with-resources so the ResultSet is fully consumed before the statement closes
When it happens
Trigger: Calling next() after rs.close() or stmt.close(); calling next() again after a previous next() threw an invalid-state SQLException; iterating the old ResultSet after TursoStatement.reset().
Common situations: finally-block loops that keep calling next() after the body threw; try-with-resources scoping where the statement closes before a later iteration; double consumption of the same statement result by helper methods.
Related errors
- ResultSet is null
- SQLite only supports TYPE_FORWARD_ONLY cursors
- SQLite only supports CONCUR_READ_ONLY cursors
- SQLite only supports closing cursors at commit
- The result set is not open
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/90ce55f8fcdb9b0a.
Report an issue: GitHub.