risingwavelabs/risingwave · warning
failed to decode webhook JSON payload
Error message
failed to decode webhook JSON payload
What it means
The webhook JSON body could not be parsed into JSON access values (`generate_json_access` failed). The request payload is not valid JSON or does not match the decoder's expectations, so the service rejects it with HTTP 422 UNPROCESSABLE_ENTITY. This is a client-side payload problem, not a server fault.
Source
Thrown at src/frontend/src/webhook/payload.rs:55
pub(crate) fn build_json_access_builder(headers: &HeaderMap) -> Result<JsonAccessBuilder> {
JsonAccessBuilder::new(json_properties_from_headers(headers)?).map_err(|e| {
err(
anyhow!(e).context("failed to build webhook JSON decoder"),
StatusCode::INTERNAL_SERVER_ERROR,
)
})
}
pub(crate) fn owned_row_from_payload_row(
access_builder: &mut JsonAccessBuilder,
columns: &[WebhookTableColumnDesc],
payload_row: &[u8],
) -> Result<OwnedRow> {
let access = access_builder
.generate_json_access(payload_row.to_vec())
.map_err(|e| {
err(
anyhow!(e).context("failed to decode webhook JSON payload"),
StatusCode::UNPROCESSABLE_ENTITY,
)
})?;
let row = columns
.iter()
.map(
|column| match access.access(&[column.name.as_str()], &column.data_type) {
Ok(datum) => Ok(datum.to_owned_datum()),
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,View on GitHub (pinned to 6469eb736d)
Solutions
- Validate the body is well-formed JSON (e.g. JSON.parse in the producer) before sending.
- Set `Content-Type: application/json` and send a UTF-8 JSON document.
- Log/inspect the exact payload bytes that were rejected and compare with the table's expected schema.
- Ensure no proxy/gateway is truncating or transforming the body.
- For large payloads, check the JSON column handling headers and payload size limits.
Example fix
// before
send(JSON.stringify({a: 1,})); // trailing comma -> invalid JSON
// after
const body = JSON.stringify({a: 1});
JSON.parse(body); // sanity check
send(body); Defensive patterns
Strategy: validation
Validate before calling
// validate payload before posting
const body = JSON.stringify(event);
JSON.parse(body); // throws locally if invalid
const res = await fetch(url, { method: 'POST', headers: {'content-type':'application/json'}, body }); Type guard
function isJsonObject(x) { return x !== null && typeof x === 'object' && !Array.isArray(x); }
if (!isJsonObject(event)) throw new Error('webhook payload must be a JSON object'); Try / catch
try {
const res = await fetch(url, { method: 'POST', headers: {'content-type':'application/json'}, body });
if (res.status === 422) throw new Error('payload rejected as invalid JSON: ' + (await res.text()));
} catch (e) { log('webhook payload error', e); } Prevention
- Always serialize with JSON.stringify and content-type application/json
- Dry-run payloads through a local JSON parser before shipping
- Log rejected payloads for replay after fixing
- Keep payloads within documented size limits
When it happens
Trigger: POST a body that is not valid JSON (trailing comma, truncated payload, HTML error page); binary or form-encoded body sent to a JSON webhook; payload exceeds decoder limits or contains a structure the accessor cannot traverse.
Common situations: Producer serializes with the wrong content type; a gateway truncates large bodies; payload is form-urlencoded or multipart instead of JSON; a failed upstream call returns an error page that gets forwarded to the webhook.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- HTTP sink with multiple columns requires a payload column
- expected JSON in the form {{"host": "endpoint url"}}, but go
- failed to parse request body
- failed to build webhook JSON decoder
- unsupported webhook payload format `{format}`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/1a45582d413db323.
Report an issue: GitHub.