tursodatabase/turso · warning · SQLException

turso only supports CLOSE_CURSORS_AT_COMMIT

Error message

turso only supports CLOSE_CURSORS_AT_COMMIT

What it means

The Turso JDBC connection only supports ResultSet.CLOSE_CURSORS_AT_COMMIT holdability, mirroring SQLite semantics where cursors are not held open across commits. setHoldability throws a plain SQLException for any other value, including HOLD_CURSORS_OVER_COMMIT, which is ironically the JDBC specification default.

Source

Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Connection.java:180

  @Override
  public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
    synchronized (this) {
      this.typeMap = map;
    }
  }

  @Override
  public int getHoldability() throws SQLException {
    connection.checkOpen();
    return ResultSet.CLOSE_CURSORS_AT_COMMIT;
  }

  @Override
  public void setHoldability(int holdability) throws SQLException {
    connection.checkOpen();
    if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
      throw new SQLException("turso only supports CLOSE_CURSORS_AT_COMMIT");
    }
  }

  @Override
  @SkipNullableCheck
  public Savepoint setSavepoint() throws SQLException {
    throw new SQLFeatureNotSupportedException("Savepoints are not supported by Turso");
  }

  @Override
  @SkipNullableCheck
  public Savepoint setSavepoint(String name) throws SQLException {
    throw new SQLFeatureNotSupportedException("Savepoints are not supported by Turso");
  }

  @Override
  public void rollback(Savepoint savepoint) throws SQLException {
    throw new SQLFeatureNotSupportedException("Savepoints are not supported by Turso");

View on GitHub (pinned to bad083fafb)

Solutions

  1. Remove the setHoldability call entirely; the driver's default is already CLOSE_CURSORS_AT_COMMIT.
  2. If holdability must be set, pass exactly ResultSet.CLOSE_CURSORS_AT_COMMIT.
  3. Set the pool's defaultHoldability to CLOSE_CURSORS_AT_COMMIT (or remove the pool property) so the pool never applies the JDBC default on its behalf.
  4. Refactor code that relies on reading a ResultSet after commit; consume result sets before committing.

Example fix

// before
conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); // throws

// after
// Option 1: do not call setHoldability at all (default is already correct).
// Option 2: if forced, use the only supported value:
conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
Defensive patterns

Strategy: validation

Validate before calling

if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
    holdability = ResultSet.CLOSE_CURSORS_AT_COMMIT; // or reject with a clear config error
}
conn.setHoldability(holdability);

Type guard

private static boolean isSupportedHoldability(int holdability) {
    return holdability == ResultSet.CLOSE_CURSORS_AT_COMMIT;
}

Try / catch

try {
    conn.setHoldability(requested);
} catch (SQLException e) {
    // driver only supports CLOSE_CURSORS_AT_COMMIT; fall back to the default
    LOG.info("holdability {} not supported; using CLOSE_CURSORS_AT_COMMIT", requested);
}

Prevention

When it happens

Trigger: conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); connection pools that apply a configured defaultHoldability (DBCP2, commons-dbcp); frameworks or app servers that set holdability during connection setup; ported code that assumes the JDBC default holdability is accepted.

Common situations: Migrating an app from PostgreSQL/MySQL drivers where holdable cursors work; DBCP2 basicDataSource.setDefaultHoldability(...) left at a non-default; libraries like JasperReports or reporting tools that explicitly request holdable cursors to keep result sets across commits.

Related errors


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