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

  1. Use 1-based positions: bind parameter i at index i + 1.
  2. Check 1 <= position <= stmt.parameterCount() before every bind and fail fast with a clear message if the argument count mismatches the SQL.
  3. Verify !stmt.isClosed() (and that the connection is open) before binding; do not bind on statements returned to a pool.
  4. 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

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


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