{"record":{"id":"fded485b605292ce","repo":"nautechsystems/nautilus_trader","slug":"invalid-funding-rate-value-e","errorCode":null,"errorMessage":"Invalid funding_rate value: {e}","messagePattern":"Invalid funding_rate value: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/common/parse.rs","lineNumber":561,"sourceCode":"    ))\n}\n\n/// Parses an [`OKXFundingRateMsg`] into a [`FundingRateUpdate`].\n///\n/// # Errors\n///\n/// Returns an error if the `funding_rate` field fails\n/// to parse into a Decimal value or `next_funding_time` fails to parse into a positive, in bounds interval.\npub fn parse_funding_rate_msg(\n    msg: &OKXFundingRateMsg,\n    instrument_id: InstrumentId,\n    ts_init: UnixNanos,\n) -> anyhow::Result<FundingRateUpdate> {\n    let funding_rate = msg\n        .funding_rate\n        .as_str()\n        .parse::<Decimal>()\n        .map_err(|e| anyhow::anyhow!(\"Invalid funding_rate value: {e}\"))?;\n\n    let funding_time = parse_millisecond_timestamp(msg.funding_time);\n    let next_funding_time = parse_millisecond_timestamp(msg.next_funding_time);\n    let funding_interval_nanos =\n        next_funding_time\n            .duration_since(&funding_time)\n            .ok_or(anyhow::anyhow!(\n                \"Invalid funding_interval, cannot be negative\"\n            ))?;\n    let funding_interval = u16::try_from(funding_interval_nanos.as_mins())\n        .context(\"funding_interval out of bounds\")?;\n    let ts_event = parse_millisecond_timestamp(msg.ts);\n\n    Ok(FundingRateUpdate::new(\n        instrument_id,\n        funding_rate,\n        Some(funding_interval),\n        Some(funding_time),","sourceCodeStart":543,"sourceCodeEnd":579,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/common/parse.rs#L543-L579","documentation":"parse_funding_rate_msg converts an OKX funding-rate channel message into a FundingRateUpdate. The funding_rate field is a string that must parse as a Decimal; if OKX sends a malformed, empty, or unexpectedly formatted value, the parse fails and this error is raised wrapping the Decimal parse error.","triggerScenarios":"A funding-rate websocket message (parsed via parse_funding_rate_msg or parse_funding_rate_msg_vec) carries a funding_rate string that is empty, non-numeric, or uses a format Decimal cannot parse (e.g. scientific notation edge cases or locale-formatted numbers).","commonSituations":"OKX sends an initial/placeholder snapshot with an empty fundingRate before the first computed value; API change in the funding-rate channel payload; intercepting messages from the wrong channel so unrelated strings land in the funding_rate field; proxy/CDN mangling the payload.","solutions":["Log msg.funding_rate and the full raw message when this fires to see the actual malformed value.","Handle empty/placeholder values by skipping the update (return Ok with early exit) rather than erroring the whole message batch.","Pre-sanitize: trim the string and reject empty before parse::<Decimal>(); consider accepting scientific notation via Decimal::from_scientific as a fallback.","Check the adapter version against the current OKX funding-rate channel schema in case the field format changed."],"exampleFix":"// before\nlet funding_rate = msg\n    .funding_rate\n    .as_str()\n    .parse::<Decimal>()\n    .map_err(|e| anyhow::anyhow!(\"Invalid funding_rate value: {e}\"))?;\n\n// after\nlet raw = msg.funding_rate.as_str().trim();\nif raw.is_empty() {\n    anyhow::bail!(\"skipping funding rate update: empty funding_rate\");\n}\nlet funding_rate = raw.parse::<Decimal>()\n    .map_err(|e| anyhow::anyhow!(\"Invalid funding_rate value: {e}\"))?;","handlingStrategy":"validation","validationCode":"fn parse_okx_decimal(s: &str) -> Option<Decimal> {\n    let s = s.trim();\n    if s.is_empty() { return None; }\n    s.parse::<Decimal>().ok()\n}","typeGuard":null,"tryCatchPattern":"match parse_funding_rate_msg(&msg, ts_init) {\n    Ok(u) => emit(u),\n    Err(e) => log::warn!(\"dropping funding rate update: {e}\"),\n}","preventionTips":["Trim and emptiness-check string numeric fields before Decimal parsing.","Treat funding-rate snapshots with placeholder values as skippable updates.","Log raw messages from the funding-rate channel so malformed payloads are quickly diagnosable."],"tags":["rust","okx","websocket","parsing","funding-rate"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}