tursodatabase/turso · error · TypeError

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

SQLite integers are signed 64-bit (-2^63 .. 2^63-1). The JS driver checks bigint bind values against this range in normalizeBatchBindValue and throws a TypeError when the value would overflow, because an out-of-range integer cannot round-trip through SQLite without corruption or silent truncation.

Source

Thrown at bindings/javascript/packages/common/promise.ts:922

        throw attachRollbackError(err, rollbackError);
      }
    }
    throw err;
  }
  return results;
}

function normalizeBatchBindValue(value: any): any {
  if (value === null || value === undefined) return null;
  if (typeof value === "number") {
    if (!Number.isFinite(value)) {
      throw new TypeError("Only finite numbers (not Infinity or NaN) can be passed as arguments");
    }
    return value;
  }
  if (typeof value === "bigint") {
    if (value < -(1n << 63n) || value > (1n << 63n) - 1n) {
      throw new TypeError("BigInt value is outside SQLite's signed 64-bit integer range");
    }
    return value;
  }
  if (
    typeof value === "boolean" ||
    typeof value === "string" ||
    (ArrayBuffer.isView(value) && !(value instanceof DataView))
  ) {
    return value;
  }
  if (value instanceof ArrayBuffer) return new Uint8Array(value);
  return String(value);
}

/**
 * A handle to an open transaction, passed as the first argument to the
 * callback of `Database.transactionAsync()`. All SQL of the transaction
 * must go through this handle: the transaction wrapper holds the database's

View on GitHub (pinned to c1e5928725)

Solutions

  1. Range-check the value before binding and clamp or wrap it into the signed 64-bit range.
  2. Bind as TEXT (value.toString()) if the value must be preserved exactly.
  3. Redesign the schema column to hold the value as TEXT or split across two columns.
  4. Use Number if the magnitude fits in a double and losslessness is acceptable (still <= 2^53).

Example fix

// before
const id = 18446744073709551615n; // u64 max
stmt.bind(id); // throws
// after
stmt.bind(id <= 9223372036854775807n ? id : id.toString());
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try { await db.batch(stmts); } catch (e) { if (e instanceof TypeError && /signed 64-bit/.test(e.message)) { /* rebind as string or clamp */ } else throw e; }

Prevention

When it happens

Trigger: Passing a BigInt bind parameter to db.batch() whose value is < -(2n**63n) or > 2n**63n - 1n, e.g. 2n**63n or -9223372036854775809n.

Common situations: Computing hashes, UUIDv7-like IDs, or crypto-derived numbers into BigInt and binding them directly; multiplying large counters; reading an unsigned u64 from another system (Rust/Go) and passing it through.

Related errors


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