risingwavelabs/risingwave · warning
unsupported webhook payload format `{format}`
Error message
unsupported webhook payload format `{format}` What it means
The `x-rw-webhook-format` header specified a payload format other than `plain` (case-insensitive). RisingWave webhooks currently only accept plain JSON payloads, so any other format value is rejected with HTTP 400 BAD_REQUEST before decoding starts.
Source
Thrown at src/frontend/src/webhook/payload.rs:82
Err(error) if column.is_pk => Err(error),
Err(_) => Ok(None),
},
)
.collect::<AccessResult<Vec<_>>>()
.map(OwnedRow::new);
row.map_err(|e| {
err(
anyhow!(e).context("failed to decode webhook JSON payload"),
StatusCode::UNPROCESSABLE_ENTITY,
)
})
}
fn json_properties_from_headers(headers: &HeaderMap) -> Result<JsonProperties> {
let format = header_value(headers, WEBHOOK_FORMAT_HEADER)?.unwrap_or_else(|| "plain".into());
if !format.eq_ignore_ascii_case("plain") {
return Err(err(
anyhow!("unsupported webhook payload format `{format}`"),
StatusCode::BAD_REQUEST,
));
}
let encode = header_value(headers, WEBHOOK_ENCODE_HEADER)?.unwrap_or_else(|| "json".into());
if !encode.eq_ignore_ascii_case("json") {
return Err(err(
anyhow!("unsupported webhook payload encoding `{encode}`"),
StatusCode::BAD_REQUEST,
));
}
let timestamp_handling =
parse_timestamp_handling(headers, WEBHOOK_JSON_TIMESTAMP_HANDLING_HEADER)?;
let timestamptz_handling =
parse_timestamptz_handling(headers, WEBHOOK_JSON_TIMESTAMPTZ_HANDLING_HEADER)?;
let time_handling = parse_time_handling(headers, WEBHOOK_JSON_TIME_HANDLING_HEADER)?;
let bigint_unsigned_handling =View on GitHub (pinned to 6469eb736d)
Solutions
- Remove the `x-rw-webhook-format` header entirely (defaults to `plain`).
- Set it explicitly to `plain` (case-insensitive).
- Send the body as raw plain JSON; use `x-rw-webhook-encode: json` for encoding, not format.
- If a non-JSON format is truly needed, transform it client-side before posting.
- Check release notes in case a newer RisingWave version adds formats.
Example fix
// before
curl -H 'x-rw-webhook-format: protobuf' -d @payload.bin $URL
// after
curl -H 'x-rw-webhook-encode: json' -H 'content-type: application/json' -d '{"a":1}' $URL Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED_FORMATS = ['plain'];
const fmt = headers['x-rw-webhook-format'];
if (fmt && !SUPPORTED_FORMATS.includes(String(fmt).toLowerCase()))
throw new Error(`unsupported webhook format: ${fmt} (only 'plain')`); Type guard
const isSupportedFormat = (v) => typeof v === 'string' && v.toLowerCase() === 'plain';
Try / catch
if (!isSupportedFormat(headers['x-rw-webhook-format'] ?? 'plain'))
throw new Error('unsupported webhook payload format');
const res = await fetch(url, { method: 'POST', headers, body }); Prevention
- Omit the x-rw-webhook-format header unless you explicitly mean plain
- Don't confuse the format header with the encode header
- Validate header names/values in the producer SDK
- Check RisingWave changelogs for newly supported formats
When it happens
Trigger: POST with header `x-rw-webhook-format: protobuf`, `csv`, or any value other than `plain` (any casing).
Common situations: Producers copy header templates from other systems expecting protobuf-encoded webhooks; a generic webhook sender adds a format header by default; typos like `plainjson` or `json` in the format header.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unsupported webhook payload encoding `{encode}`
- unrecognized value `{value}` for `{key}`
- invalid webhook JSON decoder option
- failed to decode webhook JSON payload
- Invalid value `{value}` for `{entry}`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/2904fe7a39a52423.
Report an issue: GitHub.