{"record":{"id":"6c5c897b6b243f85","repo":"tursodatabase/turso","slug":"batch-execution-failed","errorCode":null,"errorMessage":"Batch execution failed","messagePattern":"Batch execution failed","errorType":"exception","errorClass":"DatabaseError","httpStatus":null,"severity":"error","filePath":"serverless/javascript/src/session.ts","lineNumber":619,"sourceCode":"      response = await executePipeline(this.httpContext(queryOptions), request, this.createAbortSignal(queryOptions));\n    } catch (e) {\n      this.baton = null;\n      this.autocommit = true;\n      throw e;\n    }\n\n    this.baton = response.baton;\n    if (response.base_url) {\n      this.baseUrl = normalizeUrl(response.base_url);\n    }\n    this.updateAutocommit(response);\n\n    const first = response.results?.[0];\n    if (!first) {\n      throw new DatabaseError('missing batch result in pipeline response');\n    }\n    if (first.type === 'error') {\n      throw new DatabaseError(first.error?.message || 'Batch execution failed', first.error?.code);\n    }\n    if (first.response?.type !== 'batch') {\n      throw new DatabaseError(`expected batch result in pipeline response, got ${first.response?.type}`);\n    }\n    const batchResult = first.response.result as BatchResultData | undefined;\n    const stepResults = batchResult?.step_results;\n    const stepErrors = batchResult?.step_errors;\n    if (\n      !Array.isArray(stepResults) ||\n      !Array.isArray(stepErrors) ||\n      stepResults.length !== steps.length ||\n      stepErrors.length !== steps.length\n    ) {\n      throw new DatabaseError('batch response does not have one result and one error per step');\n    }\n\n    // One result per user statement, in input order; null for statements\n    // that did not complete.","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/serverless/javascript/src/session.ts#L601-L637","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait session.batch(migrationStatements, 'write'); // one bad statement kills the stream\n\n// after\nfor (const stmt of migrationStatements) {\n  try { await session.execute(stmt); }\n  catch (e) { console.error('failed:', stmt, e); throw e; }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"import { DatabaseError } from '@tursodatabase/serverless';\n\nfunction isBatchError(e: unknown): e is DatabaseError {\n  return e instanceof DatabaseError && e.message === 'Batch execution failed';\n}","tryCatchPattern":"try {\n  return await session.batch(statements, 'write');\n} catch (e) {\n  if (e instanceof DatabaseError) {\n    // atomic mode already rolled back; per-statement message/code is on the error\n    logFailedBatch(statements, e);\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["sql","batch","typescript"],"backgroundTag":"batch-execution-failed","analyzedSha":"c1e59287258d99b309e362a63f48822256e2f65f","analyzedAt":"2026-08-31T11:17:35.598Z","contentChangedAt":"2026-08-31T11:17:35.598Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}