tursodatabase/turso · error · SQLException
Exception while binding long value at position " + position
Error message
Exception while binding long value at position " + position
What it means
Thrown when the JNI-native bindLong call on a prepared statement returns a non-zero SQLite result code instead of SQLITE_OK. The native layer (bindings/java/rs_src/turso_statement.rs) returns SQLITE_ERROR in two cases: the statement pointer no longer resolves to a live statement (closed/finalized or stale handle), or bind_at rejects the parameter position as out of range. Note that parameter positions are 1-based; position 0 actually panics inside the native NonZero::new().unwrap().
Source
Thrown at bindings/java/src/main/java/tech/turso/core/TursoStatement.java:154
* @return A result code indicating the success or failure of the operation.
* @throws SQLException If a database access error occurs.
*/
public int bindInt(int position, int value) throws SQLException {
return bindLong(position, value);
}
/**
* Binds a long value to the prepared statement at the specified position.
*
* @param position The index of the SQL parameter to be set.
* @param value The value to bind to the parameter.
* @return <a href="https://www.sqlite.org/c3ref/c_abort.html">Result Codes</a>
* @throws SQLException If a database access error occurs.
*/
public int bindLong(int position, long value) throws SQLException {
final int result = bindLong(statementPointer, position, value);
if (result != 0) {
throw new SQLException("Exception while binding long value at position " + position);
}
return result;
}
private native int bindLong(long statementPointer, int position, long value) throws SQLException;
/**
* Binds a double value to the prepared statement at the specified position.
*
* @param position The index of the SQL parameter to be set.
* @param value The value to bind to the parameter.
* @return <a href="https://www.sqlite.org/c3ref/c_abort.html">Result Codes</a>
* @throws SQLException If a database access error occurs.
*/
public int bindDouble(int position, double value) throws SQLException {
final int result = bindDouble(statementPointer, position, value);
if (result != 0) {
throw new SQLException("Exception while binding double value at position " + position);View on GitHub (pinned to bad083fafb)
Solutions
- Use 1-based positions: bind parameter i at index i + 1.
- Check 1 <= position <= stmt.parameterCount() before every bind and fail fast with a clear message if the argument count mismatches the SQL.
- Verify !stmt.isClosed() (and that the connection is open) before binding; do not bind on statements returned to a pool.
- Keep statement usage confined to one thread or synchronize access, since the native pointer is released on close.
Example fix
// before
for (int i = 0; i < args.length; i++) {
stmt.bindLong(i, ((Number) args[i]).longValue()); // 0-based index: position 0 panics, off-by-one binds
}
// after
int paramCount = stmt.parameterCount();
if (args.length != paramCount) {
throw new IllegalArgumentException("SQL expects " + paramCount + " params, got " + args.length);
}
for (int i = 0; i < args.length; i++) {
stmt.bindLong(i + 1, ((Number) args[i]).longValue()); // 1-based positions
} Defensive patterns
Strategy: validation
Validate before calling
if (stmt.isClosed()) {
throw new IllegalStateException("cannot bind on closed statement");
}
int count = stmt.parameterCount();
if (position < 1 || position > count) {
throw new IllegalArgumentException(
"bind position " + position + " out of range 1.." + count + " for SQL: " + sql);
}
stmt.bindLong(position, value); Try / catch
try {
stmt.bindLong(position, value);
} catch (SQLException e) {
throw new IllegalStateException(
"bindLong failed at position " + position + " for SQL: " + sql
+ " (expected params=" + expectedParamCount + ")", e);
} Prevention
- Treat parameter positions as 1-based everywhere; never feed a 0-based loop index directly.
- Assert args.length == stmt.parameterCount() once before any bind loop.
- Build SQL text and its parameter list in the same method so they cannot diverge.
- Never bind on a statement that another thread or an error path may have closed.
When it happens
Trigger: Calling stmt.bindLong(position, value) with position greater than stmt.parameterCount(); passing a 0-based index (e.g. 0 for the first parameter); calling bindLong on a statement after close() or after its connection was closed; concurrently finalizing the statement while another thread binds.
Common situations: Loops that bind an argument array with 0-based indices; SQL whose placeholder count does not match the number of bind calls after editing the query; reusing a cached PreparedStatement after the pool recycled it; sharing a statement across threads without synchronization.
Related errors
- Exception while binding double value at position " + positio
- Exception while binding text value at position " + position
- Exception while binding blob value at position " + position
- database connection closed
- Failed to convert ${sql} into bytes
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/766519210498f06a.
Report an issue: GitHub.