risingwavelabs/risingwave · error

failed to parse request body

Error message

failed to parse request body

What it means

When the webhook body is not batched, generate_data_chunk parses the entire body as a single JSON value via Value::from_text. If parsing fails, the error is wrapped with context 'failed to parse request body' and returned with HTTP 422 (Unprocessable Entity). The webhook expects a valid JSON document per row.

Source

Thrown at src/frontend/src/webhook/mod.rs:191

        if res.status == fast_insert_response::Status::Succeeded as i32 {
            Ok(())
        } else {
            Err(err(
                anyhow!("Fast insert failed: {}", res.error_message),
                StatusCode::INTERNAL_SERVER_ERROR,
            ))
        }
    }

    fn generate_data_chunk(is_batched: bool, body: &Bytes) -> Result<DataChunk> {
        let mut builder = JsonbArrayBuilder::with_type(1, DataType::Jsonb);

        if !is_batched {
            // Use builder to obtain a single column & single row DataChunk
            let json_value = Value::from_text(body).map_err(|e| {
                err(
                    anyhow!(e).context("failed to parse request body"),
                    StatusCode::UNPROCESSABLE_ENTITY,
                )
            })?;

            let jsonb_val = JsonbVal::from(json_value);
            builder.append(Some(jsonb_val.as_scalar_ref()));

            Ok(DataChunk::new(vec![builder.finish().into_ref()], 1))
        } else {
            let rows: Vec<_> = body
                .split(|&b| b == b'\n')
                .filter(|b| !b.is_empty())
                .collect();

            for row in &rows {
                let json_value = Value::from_text(row).map_err(|e| {
                    err(
                        anyhow!(e).context("failed to parse request body"),

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Validate the body is a single well-formed JSON document (jq . body.json should succeed).
  2. Set Content-Type: application/json and send the raw JSON object as the body.
  3. If sending multiple records, use the batched endpoint format (array of objects) instead.
  4. Log the raw body server-side and re-test with curl --data-binary to rule out encoding issues.

Example fix

// before
curl -X POST -d 'key=value' .../webhook/table/orders

// after
curl -X POST -H 'Content-Type: application/json' -d '{"id":1,"item":"x"}' .../webhook/table/orders
Defensive patterns

Strategy: validation

Validate before calling

// client-side pre-check
const body = await res.text();
JSON.parse(body); // throws locally before sending if invalid
if (!body.trim().startsWith('{')) throw new Error('webhook body must be a single JSON object');

Type guard

function isJsonObject(s: string): boolean {
  try { const v = JSON.parse(s); return typeof v === 'object' && v !== null && !Array.isArray(v); }
  catch { return false; }
}

Try / catch

try {
  await postWebhook(url, body);
} catch (e) {
  if (e.status === 422 && e.message.includes('failed to parse request body')) {
    logInvalidBody(rawBody); // inspect and fix producer
  } else { throw e; }
}

Prevention

When it happens

Trigger: POSTing a non-batched webhook request whose body is not valid JSON: empty body, truncated JSON, HTML/text payloads, wrong Content-Type content, or JSON that fails jsonb parsing rules (e.g. duplicate handling, non-object roots where required).

Common situations: Senders posting form-encoded or plain-text data; proxies truncating large bodies; webhook producers emitting NDJSON (multiple JSON lines) to a single-object endpoint.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/5ea6b3568bfeb254. Report an issue: GitHub.