tursodatabase/turso · error · Error

BigInt value is outside SQLite's signed 64-bit integer range

Error message

BigInt value is outside SQLite's signed 64-bit integer range

What it means

encodeValue in the serverless (HTTP) protocol client serializes JS bind values into Turso's wire format. Bigints are serialized as integer strings, but only if they fit SQLite's signed 64-bit range; otherwise the server could not store them, so the client throws up front.

Source

Thrown at serverless/javascript/src/protocol.ts:141

export function encodeValue(value: any): Value {
  if (value === null || value === undefined) {
    return { type: 'null' };
  }
  
  if (typeof value === 'number') {
    if (!Number.isFinite(value)) {
      throw new Error("Only finite numbers (not Infinity or NaN) can be passed as arguments");
    }
    if (Number.isSafeInteger(value)) {
      return { type: 'integer', value: value.toString() };
    }
    return { type: 'float', value };
  }
  
  if (typeof value === 'bigint') {
    if (value < -(1n << 63n) || value > (1n << 63n) - 1n) {
      throw new Error("BigInt value is outside SQLite's signed 64-bit integer range");
    }
    return { type: 'integer', value: value.toString() };
  }
  
  if (typeof value === 'boolean') {
    return { type: 'integer', value: value ? '1' : '0' };
  }
  
  if (typeof value === 'string') {
    return { type: 'text', value };
  }
  
  if (value instanceof ArrayBuffer) {
    return { type: 'blob', base64: toBase64(new Uint8Array(value)) };
  }

  if (value instanceof Uint8Array) {
    return { type: 'blob', base64: toBase64(value) };

View on GitHub (pinned to c1e5928725)

Solutions

  1. Validate the bigint against the signed 64-bit range before the call.
  2. Serialize oversized values as strings and store them in a TEXT column.
  3. Clamp or mask the value (e.g. BigInt.asIntN(64, v)) if wrapping is acceptable.
  4. Change the pipeline to use Number when precision loss is tolerable.

Example fix

// before
const v = 2n ** 64n - 1n;
await client.execute({ sql: "INSERT INTO t VALUES (?)", args: [v] });
// after
const v = BigInt.asIntN(64, 2n ** 64n - 1n); // wrapped, or use v.toString()
await client.execute({ sql: "INSERT INTO t VALUES (?)", args: [v.toString()] });
Defensive patterns

Strategy: validation

Validate before calling

const MIN = -(2n**63n), MAX = 2n**63n - 1n;
if (typeof v === 'bigint' && (v < MIN || v > MAX)) throw new RangeError('bigint out of i64 range');

Type guard

const fitsI64 = (v: bigint): boolean => v >= -(2n**63n) && v <= 2n**63n - 1n;

Try / catch

try { await client.execute(stmt); } catch (e) { if (e.message?.includes('signed 64-bit')) { /* stringify or clamp the bigint */ } else throw e; }

Prevention

When it happens

Trigger: Executing a query through the serverless client (execute/batch path -> encodeSqlArgs -> encodeValue) with a BigInt parameter outside [-(2n**63n), 2n**63n-1n].

Common situations: Passing unsigned 64-bit values received from Rust/Go APIs, large product of ids, or cryptographic values straight into client.execute(...).bind(bigint).

Related errors


AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-31). Data as JSON: /api/errors/fb44062b02ce9859. Report an issue: GitHub.