tursodatabase/turso · error · DatabaseError
batch response is missing statement results
Error message
batch response is missing statement results
What it means
After decoding the batch response, batch() maps one result per user statement. If any statement slot is still null (no step result found for it), the batch did not fully execute, and returning partial data silently would hide lost statements — so it throws.
Source
Thrown at serverless/javascript/src/session.ts:682
const stepError = stepErrors[firstUserStepIdx + i];
if (stepError) {
throwStepError(stepError, i);
}
}
if (commitIdx >= 0 && stepErrors[commitIdx]) {
throwStepError(stepErrors[commitIdx]);
}
if (rollbackError) {
const error = new DatabaseError(
rollbackError.message || 'Batch rollback failed',
rollbackError.code,
);
error.batchResults = results;
throw error;
}
if (results.some(result => result === null)) {
throw new DatabaseError('batch response is missing statement results');
}
return results;
}
/** Decode one statement result of a batch response (section 8.4) into
* the per-statement result shape returned by `batch()`. */
private decodeBatchStepResult(stepResult: ExecuteResult, safeIntegers: boolean, raw: boolean): any {
const columns = (stepResult.cols ?? []).map(col => col.name ?? '');
const columnTypes = (stepResult.cols ?? []).map(col => col.decltype || '');
const rows = (stepResult.rows ?? []).map(row => {
const decoded = row.map(value => decodeValue(value, safeIntegers));
return raw ? decoded : this.createObjectRow(decoded, columns);
});
let lastInsertRowid: number | undefined;
if (stepResult.last_insert_rowid !== undefined && stepResult.last_insert_rowid !== null) {
lastInsertRowid = typeof stepResult.last_insert_rowid === 'number'
? stepResult.last_insert_rowid
: parseInt(stepResult.last_insert_rowid, 10);View on GitHub (pinned to c1e5928725)
Solutions
- Check the thrown error's batchResults property to see which statement failed and why.
- Fix the failing statement (syntax, constraint, type error) that aborted the batch.
- Use batch(..., 'true') (go: true) if you want independent execution semantics where appropriate.
- Wrap each risky statement with SAVEPOINTs or run them in separate batch calls if partial success is acceptable.
Example fix
// before
await session.batch([
{ sql: "INSERT INTO a ..." },
{ sql: "BROKEN SQL" },
{ sql: "INSERT INTO b ..." } // never runs -> null result
]);
// after
await session.batch([
{ sql: "INSERT INTO a ..." },
{ sql: "FIXED SQL" },
{ sql: "INSERT INTO b ..." }
]); Defensive patterns
Strategy: try-catch
Validate before calling
null
Try / catch
try { await session.batch(stmts); } catch (e) { if (e instanceof DatabaseError && e.message === 'batch response is missing statement results') { const failed = e.batchResults?.filter(r => r?.error); /* inspect failing statement and fix SQL */ } else throw e; } Prevention
- Validate SQL statements before batching to avoid mid-batch aborts.
- Use go:true batch mode when statements should not abort each other.
- Inspect e.batchResults on failure to pinpoint the offending statement.
When it happens
Trigger: session.batch() where stepResults contains null (or a non-completing marker) for one of the user statements — typically because an earlier step errored and the server skipped subsequent steps, or a step result was missing.
Common situations: A mid-batch SQL error aborting the remaining statements, using batch without go:true so statements run sequentially and one failure stops the rest, protocol truncation.
Related errors
- missing batch result in pipeline response
- expected batch result in pipeline response, got ${first.resp
- batch response does not have one result and one error per st
- batch mode must be one of {sorted(_BATCH_MODES)} or None, go
- batch statement {index} must be a SQL string or a (sql, para
AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-31).
Data as JSON: /api/errors/9f2e64f39ff006e3.
Report an issue: GitHub.