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

  1. Iterate exactly once with while (rs.next()) { ... } and never call next() after an exception
  2. Check rs.isOpen() before any optional extra next() call
  3. 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

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


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