tursodatabase/turso · error · DatabaseError

expected batch result in pipeline response, got ${first.resp

Error message

expected batch result in pipeline response, got ${first.response?.type}

What it means

batch() validates that the first pipeline result is of type 'batch'. Getting another type (e.g. 'error', 'close', or 'execute') means the server responded with a pipeline frame the client did not expect, so the result cannot be interpreted as batch step results.

Source

Thrown at serverless/javascript/src/session.ts:622

      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.
    const results: Array<any | null> = statements.map((_, i) => {
      const stepResult = stepResults[firstUserStepIdx + i];
      return stepResult ? this.decodeBatchStepResult(stepResult, safeIntegers, raw) : null;

View on GitHub (pinned to c1e5928725)

Solutions

  1. Check first.error in surrounding logs for the real server-side failure.
  2. Pin/upgrade client and server to compatible versions.
  3. Bypass proxies by connecting directly to the Turso URL.
  4. Capture and inspect the full pipeline response to identify the unexpected frame type.
Defensive patterns

Strategy: type-guard

Validate before calling

null

Type guard

const isBatchResult = (r: any): r is { type: 'batch'; response: { type: 'batch'; result: unknown } } => r?.response?.type === 'batch';

Try / catch

try { await session.batch(stmts); } catch (e) { if (e instanceof DatabaseError && e.message.startsWith('expected batch result')) { /* inspect server response type, check versions */ } else throw e; }

Prevention

When it happens

Trigger: Calling session.batch() where response.results[0].response.type is anything other than 'batch' — protocol version mismatch, server executed the request differently, or response frames got reordered/interleaved by a proxy.

Common situations: Client/server version skew after a server upgrade, custom HTTP intermediaries mangling JSON, hitting an endpoint that only supports the older Hrana protocol.

Related errors


AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-31). Data as JSON: /api/errors/f244ce73ab97668a. Report an issue: GitHub.