tursodatabase/turso · error · DatabaseError
Batch execution failed
Error message
Batch execution failed
What it means
Fatal, stream-level 'error' entry inside batch(). Per-statement failures arrive as step_error entries, which are captured as a deferred error so the trailing autocommit probe and (in atomic mode) the ROLLBACK step still drain; a top-level error entry means the whole cursor stream failed and is thrown immediately. The literal text is the fallback when the entry has no message.
Solutions
- Inspect the thrown message/code — the server usually names the offending statement
- Split the batch and run statements individually to isolate which one kills the stream
- Drop the mode argument (non-atomic) to see whether the implicit BEGIN/COMMIT wrapping is the trigger
- Reduce batch size or raise the query timeout if the failure correlates with long runtime
Example fix
// before
await session.batch(migrationStatements, 'write'); // one bad statement kills the stream
// after
for (const stmt of migrationStatements) {
try { await session.execute(stmt); }
catch (e) { console.error('failed:', stmt, e); throw e; }
} Defensive patterns
Strategy: try-catch
Type guard
import { DatabaseError } from '@tursodatabase/serverless';
function isBatchError(e: unknown): e is DatabaseError {
return e instanceof DatabaseError && e.message === 'Batch execution failed';
} Try / catch
try {
return await session.batch(statements, 'write');
} catch (e) {
if (e instanceof DatabaseError) {
// atomic mode already rolled back; per-statement message/code is on the error
logFailedBatch(statements, e);
}
throw e;
} Prevention
- In atomic mode a failed batch rolls back automatically — do not add manual compensating writes
- Split very large batches; long runtimes amplify stream-level failures
- Dry-run migration batches statement-by-statement in a dev environment before sending them as one batch
- Remember per-step errors are deferred until the rollback and probe drain, so the surfaced error is the first (root cause) one
When it happens
Trigger: The server aborting the cursor stream mid-batch (connection/stream failure); batches whose statements are not allowed together (e.g. certain DDL inside the implicitly wrapped BEGIN...COMMIT of atomic mode); resource limits killing the stream. In atomic mode a user-step failure instead surfaces as the deferred DatabaseError after the rollback is observed.
Common situations: Large multi-migration batches run with a mode ('write'/'immediate') hitting a server limit; one statement in a long batch invalidating the stream; network interruption during a long batch.
Related errors
- batch statement failed: is not allowed in an atomic batch
- batch statement failed
- Describe execution failed
- Expected first argument to be an array of statements
- Sequence execution failed
AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-31).
Data as JSON: /api/errors/6c5c897b6b243f85.
Report an issue: GitHub.
Appendix: source
Thrown at serverless/javascript/src/session.ts:619
response = await executePipeline(this.httpContext(queryOptions), request, this.createAbortSignal(queryOptions));
} catch (e) {
this.baton = null;
this.autocommit = true;
throw e;
}
this.baton = response.baton;
if (response.base_url) {
this.baseUrl = normalizeUrl(response.base_url);
}
this.updateAutocommit(response);
const first = response.results?.[0];
if (!first) {
throw new DatabaseError('missing batch result in pipeline response');
}
if (first.type === 'error') {
throw new DatabaseError(first.error?.message || 'Batch execution failed', first.error?.code);
}
if (first.response?.type !== 'batch') {
throw new DatabaseError(`expected batch result in pipeline response, got ${first.response?.type}`);
}
const batchResult = first.response.result as BatchResultData | undefined;
const stepResults = batchResult?.step_results;
const stepErrors = batchResult?.step_errors;
if (
!Array.isArray(stepResults) ||
!Array.isArray(stepErrors) ||
stepResults.length !== steps.length ||
stepErrors.length !== steps.length
) {
throw new DatabaseError('batch response does not have one result and one error per step');
}
// One result per user statement, in input order; null for statements
// that did not complete.View on GitHub (pinned to c1e5928725)