{"record":{"id":"d6c418e9da17efec","repo":"tursodatabase/turso","slug":"exception-while-retrieving-parameter-count","errorCode":null,"errorMessage":"Exception while retrieving parameter count","messagePattern":"Exception while retrieving parameter count","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/core/TursoStatement.java","lineNumber":285,"sourceCode":"    if (result == -1) {\n      throw new SQLException(\"Exception while retrieving number of changes\");\n    }\n\n    return result;\n  }\n\n  private native long changes(long statementPointer) throws SQLException;\n\n  /**\n   * Returns the number of parameters in this statement. Parameters are the `?`'s that get replaced\n   * by the provided arguments.\n   *\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","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/core/TursoStatement.java#L267-L303","documentation":"Thrown when the native parameterCount call returns -1. In the native layer, -1 is only produced when the statement pointer cannot be resolved to a live statement; a live statement always returns its actual placeholder count. Hitting this means the statement was already closed, finalized, or its native handle is stale.","triggerScenarios":"Calling stmt.parameterCount() after close(); on a statement whose connection is closed; from code that holds a statement across requests after a pool recycled it.","commonSituations":"Validation helpers that count parameters late in a request lifecycle; retry logic that revalidates a cached statement after an error already closed it; middleware that inspects statements during shutdown.","solutions":["Query parameterCount() right after preparing the statement and cache the value.","Check isClosed() before calling when the statement's lifecycle is uncertain.","Re-prepare the statement instead of resurrecting a closed one.","Bind positions against the cached count rather than re-querying it after execution."],"exampleFix":"// before\nTursoStatement stmt = conn.prepare(sql);\nstmt.close();\nint params = stmt.parameterCount(); // throws: statement closed\n\n// after\nTursoStatement stmt = conn.prepare(sql);\nint params = stmt.parameterCount(); // capture immediately after prepare\nstmt.close();","handlingStrategy":"validation","validationCode":"if (!stmt.isClosed()) {\n    int params = stmt.parameterCount();\n} else {\n    throw new IllegalStateException(\"cannot query parameterCount on closed statement\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    paramCount = stmt.parameterCount();\n} catch (SQLException e) {\n    throw new IllegalStateException(\"statement no longer open\", e);\n}","preventionTips":["Cache parameterCount() once, right after prepare.","Validate bind positions against the cached count, not a late re-query.","Treat a closed statement as a signal to re-prepare, never to introspect.","Keep prepare/inspect/bind/execute inside one owning scope."],"tags":["java","jdbc","parameter-count","statement-lifecycle","use-after-close"],"backgroundTag":"closed-statement-access","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}