tursodatabase/turso · error · Error

Only finite numbers (not Infinity or NaN) can be passed as a

Error message

Only finite numbers (not Infinity or NaN) can be passed as arguments

What it means

Thrown by the wire encoder (encodeValue in protocol.ts) when a bound parameter is a number that is not finite — NaN, Infinity, or -Infinity. SQLite has no storage representation for these values, so the driver rejects them client-side before any request is sent; use null, or store the float as text, instead.

Source

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

    error?: {
      message: string;
      code: string;
    };
  }>;
}

function toBase64(uint8: Uint8Array): string {
  return Buffer.from(uint8.buffer, uint8.byteOffset, uint8.byteLength).toString('base64');
}

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') {
    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 };
  }

View on GitHub (pinned to bad083fafb)

Solutions

  1. Fix the upstream computation so it cannot produce NaN/Infinity (guard empty arrays, validate parseFloat results, check divisors)
  2. Coerce unusable numbers to null before binding: db.run(sql, Number.isFinite(v) ? v : null)
  3. Validate parameter arrays with Number.isFinite() before executing the statement

Example fix

// before
const ratio = total / count; // NaN when count === 0
await db.run("INSERT INTO stats(ratio) VALUES (?)", ratio);

// after
const ratio = count === 0 ? null : total / count;
await db.run("INSERT INTO stats(ratio) VALUES (?)", ratio);
Defensive patterns

Strategy: validation

Validate before calling

const safe = (v: unknown) =>
  typeof v === "number" && !Number.isFinite(v) ? null : v;
await db.run("INSERT INTO metrics(ratio) VALUES (?)", safe(total / count));

Type guard

const isFiniteNumber = (v: unknown): v is number =>
  typeof v === "number" && Number.isFinite(v);

Try / catch

try {
  await stmt.run([value]);
} catch (e) {
  if (e instanceof Error && e.message.includes("Only finite numbers")) {
    await stmt.run([null]); // or fix the upstream computation
  } else throw e;
}

Prevention

When it happens

Trigger: Binding a computed value that is NaN (Number(undefined), parseFloat(''), undefined + 1) or Infinity (x / 0, Number.MAX_VALUE overflow); passing Number.POSITIVE_INFINITY / Number.NaN explicitly as an argument to run/get/all/batch/execute.

Common situations: Averaging an empty array (sum/count === NaN when count is 0); optional fields whose value is undefined reaching the bind call; parseFloat on user input that is not numeric; ratio metrics dividing by a zero denominator.

Related errors


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