risingwavelabs/risingwave · warning

unsupported webhook payload encoding `{encode}`

Error message

unsupported webhook payload encoding `{encode}`

What it means

The `x-rw-webhook-encode` header specified an encoding other than `json`. Only JSON encoding is accepted for webhook payloads, so any other value is rejected with HTTP 400 BAD_REQUEST at configuration parsing time.

Source

Thrown at src/frontend/src/webhook/payload.rs:90

            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 =
        parse_bigint_unsigned_handling(headers, WEBHOOK_JSON_BIGINT_UNSIGNED_HANDLING_HEADER)?;
    let handle_toast_columns =
        parse_bool_header(headers, WEBHOOK_JSON_HANDLE_TOAST_COLUMNS_HEADER)?.unwrap_or(false);

    Ok(JsonProperties {
        use_schema_registry: false,
        timestamp_handling,
        timestamptz_handling,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Send the header value as `json` (or drop the header; `json` is the default).
  2. Pre-decode on the client: send raw JSON bytes, not base64/gzip payloads (HTTP-level compression is handled by the service's own compression layer).
  3. Fix producer SDK defaults that inject foreign encode values.
  4. If compression is needed, use standard `Content-Encoding` instead of the webhook encode header.
  5. Trim whitespace and check for near-misses like `jsonl`.

Example fix

// before
curl -H 'x-rw-webhook-encode: base64' --data-binary @body.b64 $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_ENCODES = ['json'];
const enc = headers['x-rw-webhook-encode'];
if (enc && !SUPPORTED_ENCODES.includes(String(enc).toLowerCase().trim()))
  throw new Error(`unsupported webhook encode: ${enc} (only 'json')`);

Type guard

const isSupportedEncode = (v) => typeof v === 'string' && v.trim().toLowerCase() === 'json';

Try / catch

if (!isSupportedEncode(headers['x-rw-webhook-encode'] ?? 'json'))
  throw new Error('unsupported webhook payload encoding');
const res = await fetch(url, { method: 'POST', headers, body });

Prevention

When it happens

Trigger: POST with header `x-rw-webhook-encode: base64`, `gzip`, or any non-`json` value failing the case-insensitive check.

Common situations: Producers send gzip/base64-encoded bodies and set the encode header accordingly, expecting server-side decoding; an SDK emits a default encode header value from another product; client-side compression configuration leaks into the 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


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