{"record":{"id":"35d9d42dfa9e40e8","repo":"tursodatabase/turso","slug":"exception-while-resetting-statement","errorCode":null,"errorMessage":"Exception while resetting statement","messagePattern":"Exception while resetting statement","errorType":"exception","errorClass":"java.sql.SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/core/TursoStatement.java","lineNumber":297,"sourceCode":"   *\n   * @throws SQLException If a database access error occurs\n   */\n  public int parameterCount() throws SQLException {\n    final int result = parameterCount(statementPointer);\n    if (result == -1) {\n      throw new SQLException(\"Exception while retrieving parameter count\");\n    }\n\n    return result;\n  }\n\n  private native int parameterCount(long statementPointer) throws SQLException;\n\n  /** Resets this statement so it's ready for re-execution */\n  public void reset() throws SQLException {\n    final int result = reset(statementPointer);\n    if (result == -1) {\n      throw new SQLException(\"Exception while resetting statement\");\n    }\n    this.resultSet = TursoResultSet.of(this);\n  }\n\n  private native int reset(long statementPointer) throws SQLException;\n\n  /**\n   * Checks if the statement is closed.\n   *\n   * @return true if the statement is closed, false otherwise.\n   */\n  public boolean isClosed() {\n    return closed;\n  }\n\n  @Override\n  public String toString() {\n    return (\"tursoStatement{\"","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/java/src/main/java/tech/turso/core/TursoStatement.java#L279-L315","documentation":"TursoStatement.reset() calls the native reset(pointer) JNI method (bindings/java/rs_src/turso_statement.rs:347) to clear bindings and prepare the statement for re-execution; on success the wrapper also rebuilds its resultSet. The native method returns -1 both when the statement pointer is invalid (closed statement) and when the underlying stmt.reset() itself fails, and TursoStatement.java:297 converts that -1 into this SQLException. So it fires either on a dead handle or on a genuine engine-level reset failure.","triggerScenarios":"Calling reset() after statement.close(); calling reset() after the connection was closed; re-execution loops (batch runners, connection pools resetting statements for reuse) that hit an engine error during reset; interleaving reset() with an active ResultSet iteration on the same statement.","commonSituations":"Manual statement-reuse code that calls reset() in a finally block after cleanup already ran; pool implementations (DBCP2) that call reset/clearBindings on returned statements; long-lived statements that get invalidated when the parent connection is closed by a health check; porting sqlite-jdbc reuse patterns to turso.","solutions":["Check isClosed() before reset() and skip or re-prepare instead of resetting a dead handle.","Call reset() only while you still own the statement and before any close() in your control flow.","If reset() fails on an open statement, catch SQLException, inspect any underlying native error, and fall back to closing and re-preparing the statement.","Avoid reset() inside finally blocks that run after the normal close path; track statement ownership explicitly.","Upgrade the turso bindings if an open, freshly used statement keeps failing to reset - that is an engine-level bug worth reporting."],"exampleFix":"// before\nfinally {\n    stmt.reset(); // runs even after close() -> SQLException\n}\n\n// after\nfinally {\n    if (!stmt.isClosed()) {\n        stmt.reset();\n    }\n}","handlingStrategy":"try-catch","validationCode":"if (stmt != null && !stmt.isClosed()) {\n    stmt.reset();\n}","typeGuard":null,"tryCatchPattern":"try {\n    stmt.reset();\n} catch (SQLException e) {\n    // fall back: close and re-prepare instead of resetting\n    stmt.close();\n    stmt = conn.prepare(sql);\n}","preventionTips":["Call reset() only while you own the statement and no close() has run.","Do not call reset() in finally blocks that execute after the normal close path.","Prefer re-preparing over resetting pooled or long-lived statements when in doubt.","Check isClosed() before reset in reuse loops."],"tags":["java","jdbc","turso","sqlite","statement-lifecycle","jni"],"backgroundTag":"closed-statement-handle","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}