tursodatabase/turso · error · TypeError
batch statement ${index} failed: ${message}
Error message
batch statement ${index} failed: ${message} What it means
During client.batch(), each statement's args are normalized (converts JS bind values to the wire format). If normalization throws for statement at zero-based index i, the library rethrows batchInputError(i, error) producing 'batch statement i failed: <message>' so the caller knows which statement contained the unencodable argument.
Source
Thrown at bindings/javascript/packages/common/promise.ts:799
exec.reset();
}
};
const { mode, raw } = normalizeBatchOptions(options);
const wrap = mode != null && !native.inTransaction();
const normalizedStatements = statements.map((statement, index): BatchStatement => {
if (typeof statement === "string" || statement.args === undefined) {
return statement;
}
try {
const args = Array.isArray(statement.args)
? statement.args.map(normalizeBatchBindValue)
: Object.fromEntries(
Object.entries(statement.args).map(([name, value]) => [name, normalizeBatchBindValue(value)]),
);
return { sql: statement.sql, args };
} catch (error) {
throw batchInputError(index, error);
}
});
if (wrap) {
for (let index = 0; index < normalizedStatements.length; index++) {
const statement = normalizedStatements[index];
const sql = typeof statement === "string" ? statement : statement.sql;
const keyword = firstSqlKeyword(sql);
if (keyword !== undefined && TRANSACTION_CONTROL_KEYWORDS.has(keyword)) {
throw batchInputError(index, new Error(`${keyword} is not allowed in an atomic batch`));
}
}
}
if (wrap) {
await runRawSql(`BEGIN ${normalizeBatchMode(mode!)}`);
}
const results: ResultSet[] = [];
const executeStatement = async (View on GitHub (pinned to c1e5928725)
Solutions
- Read the index in the error message and inspect that statement's args for unsupported values.
- Coerce values to supported bind types: number, string, bigint (within i64), ArrayBuffer/Uint8Array, or null.
- Replace undefined with null explicitly before batching.
- Use normalize/sanitize helpers on the args array/object before calling batch().
Example fix
// before
await db.batch([{ sql: "INSERT INTO t VALUES (?)", args: [user.createdAt] }]); // Date/undefined
// after
const safe = (v) => v === undefined ? null : (v instanceof Date ? v.toISOString() : v);
await db.batch([{ sql: "INSERT INTO t VALUES (?)", args: [safe(user.createdAt)] }]); Defensive patterns
Strategy: validation
Validate before calling
function isBindable(v) {
return v === null || typeof v === 'number' || typeof v === 'string' ||
(typeof v === 'bigint' && v >= -(2n**63n) && v < 2n**63n) ||
v instanceof Uint8Array || v instanceof ArrayBuffer;
}
statements.forEach((s, i) => (Array.isArray(s.args) ? s.args : Object.values(s.args ?? {}))
.forEach(v => { if (!isBindable(v)) throw new Error(`bad arg in statement ${i}: ${v}`); })); Type guard
const isBindable = (v: unknown): v is string | number | bigint | Uint8Array | ArrayBuffer | null => v === null || typeof v === 'number' || typeof v === 'string' || (typeof v === 'bigint' && v >= -(2n**63n) && v < 2n**63n) || v instanceof Uint8Array || v instanceof ArrayBuffer;
Try / catch
try {
const results = await db.batch(statements);
} catch (e) {
if (typeof e.message === 'string' && /batch statement \d+ failed/.test(e.message)) {
const idx = Number(e.message.match(/\d+/)[0]);
console.error(`Statement ${idx} has invalid args`, statements[idx].args);
} else throw e;
} Prevention
- Coerce optional fields with ?? null before batching
- Convert Date and class instances to strings/JSON explicitly
- Range-check BigInt values to signed 64-bit
- Validate args against a whitelist of bindable types before calling batch()
When it happens
Trigger: Calling batch() with a statement whose args contain values that cannot be bound: unsupported JS types (undefined, objects, functions, BigInt out of range), invalid named-parameter containers, or normalizeBatchBindValue rejecting a value.
Common situations: Passing undefined from an unpopulated object field; passing a Date/class instance instead of a primitive; mixing named args object with array expectations; large BigInt values beyond i64 range.
Related errors
- batch statement ${index} failed: ${keyword} is not allowed i
- batch statement ${index} failed: ${message}
- Expected first argument to be an array of statements
- Batch execution failed
- batch statement ${index} failed: ${keyword} is not allowed i
AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-31).
Data as JSON: /api/errors/f48bac72dab542d8.
Report an issue: GitHub.