{"record":{"id":"fb44062b02ce9859","repo":"tursodatabase/turso","slug":"bigint-value-is-outside-sqlite-s-signed-64-bit-int-fb4406","errorCode":null,"errorMessage":"BigInt value is outside SQLite's signed 64-bit integer range","messagePattern":"BigInt value is outside SQLite's signed 64-bit integer range","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"serverless/javascript/src/protocol.ts","lineNumber":141,"sourceCode":"\nexport function encodeValue(value: any): Value {\n  if (value === null || value === undefined) {\n    return { type: 'null' };\n  }\n  \n  if (typeof value === 'number') {\n    if (!Number.isFinite(value)) {\n      throw new Error(\"Only finite numbers (not Infinity or NaN) can be passed as arguments\");\n    }\n    if (Number.isSafeInteger(value)) {\n      return { type: 'integer', value: value.toString() };\n    }\n    return { type: 'float', value };\n  }\n  \n  if (typeof value === 'bigint') {\n    if (value < -(1n << 63n) || value > (1n << 63n) - 1n) {\n      throw new Error(\"BigInt value is outside SQLite's signed 64-bit integer range\");\n    }\n    return { type: 'integer', value: value.toString() };\n  }\n  \n  if (typeof value === 'boolean') {\n    return { type: 'integer', value: value ? '1' : '0' };\n  }\n  \n  if (typeof value === 'string') {\n    return { type: 'text', value };\n  }\n  \n  if (value instanceof ArrayBuffer) {\n    return { type: 'blob', base64: toBase64(new Uint8Array(value)) };\n  }\n\n  if (value instanceof Uint8Array) {\n    return { type: 'blob', base64: toBase64(value) };","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/serverless/javascript/src/protocol.ts#L123-L159","documentation":"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.","triggerScenarios":"Executing a query through the serverless client (execute/batch path -> encodeSqlArgs -> encodeValue) with a BigInt parameter outside [-(2n**63n), 2n**63n-1n].","commonSituations":"Passing unsigned 64-bit values received from Rust/Go APIs, large product of ids, or cryptographic values straight into client.execute(...).bind(bigint).","solutions":["Validate the bigint against the signed 64-bit range before the call.","Serialize oversized values as strings and store them in a TEXT column.","Clamp or mask the value (e.g. BigInt.asIntN(64, v)) if wrapping is acceptable.","Change the pipeline to use Number when precision loss is tolerable."],"exampleFix":"// before\nconst v = 2n ** 64n - 1n;\nawait client.execute({ sql: \"INSERT INTO t VALUES (?)\", args: [v] });\n// after\nconst v = BigInt.asIntN(64, 2n ** 64n - 1n); // wrapped, or use v.toString()\nawait client.execute({ sql: \"INSERT INTO t VALUES (?)\", args: [v.toString()] });","handlingStrategy":"validation","validationCode":"const MIN = -(2n**63n), MAX = 2n**63n - 1n;\nif (typeof v === 'bigint' && (v < MIN || v > MAX)) throw new RangeError('bigint out of i64 range');","typeGuard":"const fitsI64 = (v: bigint): boolean => v >= -(2n**63n) && v <= 2n**63n - 1n;","tryCatchPattern":"try { await client.execute(stmt); } catch (e) { if (e.message?.includes('signed 64-bit')) { /* stringify or clamp the bigint */ } else throw e; }","preventionTips":["Centralize arg encoding through one helper that range-checks bigints.","Convert u64 values from other systems to strings before they reach the client.","Add boundary-value tests for the serverless client."],"tags":["javascript","serverless","bigint","serialization"],"backgroundTag":"bigint-out-of-range","analyzedSha":"c1e59287258d99b309e362a63f48822256e2f65f","analyzedAt":"2026-08-31T11:17:35.598Z","contentChangedAt":"2026-08-31T11:17:35.598Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}