tursodatabase/turso · error · SQLException
Exception while retrieving parameter count
Error message
Exception while retrieving parameter count
What it means
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.
Source
Thrown at bindings/java/src/main/java/tech/turso/core/TursoStatement.java:285
if (result == -1) {
throw new SQLException("Exception while retrieving number of changes");
}
return result;
}
private native long changes(long statementPointer) throws SQLException;
/**
* Returns the number of parameters in this statement. Parameters are the `?`'s that get replaced
* by the provided arguments.
*
* @throws SQLException If a database access error occurs
*/
public int parameterCount() throws SQLException {
final int result = parameterCount(statementPointer);
if (result == -1) {
throw new SQLException("Exception while retrieving parameter count");
}
return result;
}
private native int parameterCount(long statementPointer) throws SQLException;
/** Resets this statement so it's ready for re-execution */
public void reset() throws SQLException {
final int result = reset(statementPointer);
if (result == -1) {
throw new SQLException("Exception while resetting statement");
}
this.resultSet = TursoResultSet.of(this);
}
private native int reset(long statementPointer) throws SQLException;
View on GitHub (pinned to bad083fafb)
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.
Example fix
// before TursoStatement stmt = conn.prepare(sql); stmt.close(); int params = stmt.parameterCount(); // throws: statement closed // after TursoStatement stmt = conn.prepare(sql); int params = stmt.parameterCount(); // capture immediately after prepare stmt.close();
Defensive patterns
Strategy: validation
Validate before calling
if (!stmt.isClosed()) {
int params = stmt.parameterCount();
} else {
throw new IllegalStateException("cannot query parameterCount on closed statement");
} Try / catch
try {
paramCount = stmt.parameterCount();
} catch (SQLException e) {
throw new IllegalStateException("statement no longer open", e);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Exception while retrieving total number of changes
- Exception while retrieving number of changes
- Exception while resetting statement
- database connection closed
- Failed to convert ${sql} into bytes
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/d6c418e9da17efec.
Report an issue: GitHub.