tursodatabase/turso · error

Failed to parse pipeline request: {}

Error message

Failed to parse pipeline request: {}

What it means

The test sync server's POST /v2/pipeline endpoint parses the request body with serde_json into PipelineReqBody. This error means the body is not valid JSON for that schema; the serde message is appended and names the offending field. PipelineReqBody expects an object with a requests array whose entries are Execute or Batch stream requests.

Source

Thrown at cli/sync_server.rs:303

                error!("Request error: {}", e);
                HttpResponse {
                    status: 500,
                    content_type: "text/plain".to_string(),
                    body: format!("Internal Server Error: {e}").into_bytes(),
                }
            }
        };

        let response_bytes = format_http_response(&http_response);
        stream.write_all(&response_bytes)?;
        stream.flush()?;

        Ok(())
    }

    fn handle_pipeline(&self, db: &DbHandle, body: &[u8]) -> Result<HttpResponse> {
        let req: PipelineReqBody = serde_json::from_slice(body)
            .map_err(|e| anyhow!("Failed to parse pipeline request: {}", e))?;

        debug!("Pipeline request: {:?}", req);

        let conn = db.conn.lock().unwrap();

        let mut results = Vec::new();

        for request in req.requests {
            let result = match request {
                StreamRequest::Execute(exec_req) => self.execute_statement(&conn, &exec_req),
                StreamRequest::Batch(batch_req) => self.execute_batch(&conn, &batch_req),
                StreamRequest::None => StreamResult::Error {
                    error: Error {
                        message: "Unknown request type".to_string(),
                        code: "UNKNOWN".to_string(),
                    },
                },
            };

View on GitHub (pinned to 492c4a71cd)

Solutions

  1. Log the exact request body and compare it field-by-field against the PipelineReqBody / StreamRequest serde types in this server build
  2. Fix the payload: top-level requests array; each entry is an Execute or Batch object with the expected fields
  3. Rebuild client and server from the same revision so the generated JSON shapes match
  4. Send the body produced by the client library's serializer instead of constructing JSON by hand

Example fix

// before
curl -d '{"request": [{"stmt": {"sql": "SELECT 1"}}]}' localhost:8080/v2/pipeline

// after
curl -d '{"requests": [{"Execute": {"stmt": {"sql": "SELECT 1"}}}]}' localhost:8080/v2/pipeline
Defensive patterns

Strategy: validation

Validate before calling

function validatePipelineRequest(body) {
  const parsed = JSON.parse(body); // throws early on bad JSON
  if (!parsed || !Array.isArray(parsed.requests)) {
    throw new Error('requests must be an array');
  }
  for (const r of parsed.requests) {
    if (!(('Execute' in r) || ('Batch' in r))) {
      throw new Error('each entry must be Execute or Batch');
    }
  }
  return parsed;
}

Type guard

function isPipelineRequest(v: unknown): v is { requests: unknown[] } {
  return typeof v === 'object' && v !== null && Array.isArray((v as any).requests);
}

Try / catch

// server/operator side: surface the serde message with a 400-style response
match self.handle_pipeline(&body) {
    Ok(resp) => resp,
    Err(e) if e.to_string().starts_with("Failed to parse pipeline request") => {
        HttpResponse { status: 400, content_type: "text/plain".into(), body: e.to_string().into_bytes() }
    }
    Err(e) => /* 500 */,
}

Prevention

When it happens

Trigger: POSTing to /v2/pipeline with syntactically invalid JSON, a missing or non-array requests field, entries whose shape matches neither StreamRequest::Execute nor StreamRequest::Batch, or wrong field types (e.g. args not an array).

Common situations: Hand-written curl payloads during debugging; client and server built from different commits so the PipelineReqBody JSON contract drifted; a proxy truncating or rewriting bodies; sending the protobuf /pull-updates payload to the JSON pipeline route by mistake.

Understand the failure class

Related errors


AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-09-13). Data as JSON: /api/errors/a670a1ee791bced6. Report an issue: GitHub.