{"record":{"id":"a5ceb44b2d64fccf","repo":"risingwavelabs/risingwave","slug":"invalid-webhook-json-decoder-option","errorCode":null,"errorMessage":"invalid webhook JSON decoder option","messagePattern":"invalid webhook JSON decoder option","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"src/frontend/src/webhook/payload.rs","lineNumber":140,"sourceCode":"        Some(value) => Err(err(\n            anyhow!(\"unrecognized value `{value}` for `{key}`\"),\n            StatusCode::BAD_REQUEST,\n        )),\n        None => Ok(None),\n    }\n}\n\nfn parse_timestamptz_handling(\n    headers: &HeaderMap,\n    key: &'static str,\n) -> Result<Option<TimestamptzHandling>> {\n    header_value(headers, key)?\n        .as_deref()\n        .map(TimestamptzHandling::from_options)\n        .transpose()\n        .map_err(|e| {\n            err(\n                anyhow!(e).context(\"invalid webhook JSON decoder option\"),\n                StatusCode::BAD_REQUEST,\n            )\n        })\n}\n\nfn parse_time_handling(headers: &HeaderMap, key: &'static str) -> Result<Option<TimeHandling>> {\n    match header_value(headers, key)?.as_deref() {\n        Some(\"milli\") => Ok(Some(TimeHandling::Milli)),\n        Some(\"micro\") => Ok(Some(TimeHandling::Micro)),\n        Some(value) => Err(err(\n            anyhow!(\"unrecognized value `{value}` for `{key}`\"),\n            StatusCode::BAD_REQUEST,\n        )),\n        None => Ok(None),\n    }\n}\n\nfn parse_bigint_unsigned_handling(","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/webhook/payload.rs#L122-L158","documentation":"The value of a timestamptz-handling header (`x-rw-webhook-json-timestamptz-handling`) could not be parsed by `TimestamptzHandling::from_options`. The inner error from that parser explains the specific problem; the wrapper marks it as an invalid webhook JSON decoder option and returns HTTP 400 BAD_REQUEST.","triggerScenarios":"POST with an unsupported or malformed timestamptz option value in the `x-rw-webhook-json-*` header (unknown handling mode, or an option string whose format `from_options` does not accept).","commonSituations":"Typos in option names; an SDK emitting option strings from a different RisingWave version; manually constructed headers with wrong option syntax (separators/flags).","solutions":["Read the inner error to identify exactly which timestamptz option failed.","Use only documented timestamptz handling values for your RisingWave version.","Remove the header to fall back to default timestamptz behavior.","Check `TimestamptzHandling::from_options` in the source for the accepted option syntax.","Test the header combination with a single curl request before enabling it in production."],"exampleFix":"// before\n-H 'x-rw-webhook-json-timestamptz-handling: utc+garbage'\n// after: remove the header (default) or use a documented mode\n// -H 'x-rw-webhook-json-timestamptz-handling: <documented-mode>'","handlingStrategy":"validation","validationCode":"// only send the header when the value is a documented mode\nconst SUPPORTED = ['milli', 'guess_number_unit']; // confirm against your RW version's TimestamptzHandling docs\nconst v = headers['x-rw-webhook-json-timestamptz-handling'];\nif (v && !SUPPORTED.includes(String(v))) throw new Error(`invalid timestamptz option: ${v}`);","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(url, { method: 'POST', headers, body });\n  if (res.status === 400 && (await res.text()).includes('invalid webhook JSON decoder option')) {\n    delete headers['x-rw-webhook-json-timestamptz-handling']; // fall back to defaults\n    return fetch(url, { method: 'POST', headers, body });\n  }\n} catch (e) { log(e); }","preventionTips":["Keep decoder headers versioned with your RisingWave deployment","Prefer omitting optional decoder headers","Validate header combos in staging","Log full headers on 400 responses to speed diagnosis"],"tags":["webhook","http-header","validation","config"],"backgroundTag":"invalid-config-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}