{"record":{"id":"fa404dbddb37a380","repo":"nautechsystems/nautilus_trader","slug":"invalid-funding-rate-timestamp","errorCode":null,"errorMessage":"invalid funding_rate_timestamp","messagePattern":"invalid funding_rate_timestamp","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/http/client.rs","lineNumber":3903,"sourceCode":"            {\n                break;\n            }\n\n            // Move end time backwards to get earlier data\n            current_end_ms = Some(earliest_funding_time - 1);\n        }\n\n        if let Some(limit_val) = limit {\n            raw_funding_rates.truncate(limit_val as usize);\n        }\n        let mut rates: Vec<FundingRateUpdate> = Vec::with_capacity(raw_funding_rates.len());\n\n        for window in raw_funding_rates.windows(2) {\n            let raw = &window[0];\n            let timestamp = raw\n                .funding_rate_timestamp\n                .parse::<i64>()\n                .map_err(|_| anyhow::anyhow!(\"invalid funding_rate_timestamp\"))?;\n            let older_timestamp = window[1]\n                .funding_rate_timestamp\n                .parse::<i64>()\n                .map_err(|_| anyhow::anyhow!(\"invalid funding_rate_timestamp\"))?;\n\n            let interval_millis = timestamp - older_timestamp;\n            let rate = parse_funding_rate(raw, &instrument, Some(interval_millis))?;\n\n            rates.push(rate);\n        }\n\n        if let Some(last_raw) = raw_funding_rates.last() {\n            let rate = parse_funding_rate(last_raw, &instrument, None)?;\n            rates.push(rate);\n        }\n\n        rates.reverse();\n","sourceCodeStart":3885,"sourceCodeEnd":3921,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/http/client.rs#L3885-L3921","documentation":"When computing funding-rate intervals, the client parses each funding_rate_timestamp from Bybit's response as an i64 millisecond epoch. If the string is non-numeric or empty the parse fails and the code returns 'invalid funding_rate_timestamp' via anyhow::anyhow!. This guards against malformed/unexpected payloads from Bybit's funding-rate history endpoint before computing the interval between consecutive windows.","triggerScenarios":"Bybit returning a funding-rate history row whose funding_rate_timestamp is empty, null serialized as empty string, or format-changed (e.g. ISO datetime instead of millis); newer Bybit API versions altering the field; hitting testnet or an endpoint variant with a different schema.","commonSituations":"Bybit API schema changes breaking older client versions; proxy/mocked endpoints returning different timestamp formats; requesting funding rates for symbols/product types whose history rows lack the field.","solutions":["Upgrade the nautilus_bybit crate / Bybit adapter to a version matching the current Bybit v5 API schema","Log or dump the raw funding-rate response to inspect the actual timestamp format returned","Retry the request — transient malformed responses can occur; verify it reproduces consistently","If the format changed, patch the parse site (crates/adapters/bybit/src/http/client.rs:3903) to handle the new format and report upstream"],"exampleFix":"// before\nlet timestamp = raw.funding_rate_timestamp.parse::<i64>()\n    .map_err(|_| anyhow::anyhow!(\"invalid funding_rate_timestamp\"))?;\n// after\nlet timestamp = raw.funding_rate_timestamp.parse::<i64>()\n    .with_context(|| format!(\"invalid funding_rate_timestamp: {:?}\", raw.funding_rate_timestamp))?;\n// or upgrade to the adapter version that matches the current Bybit schema","handlingStrategy":"try-catch","validationCode":"fn valid_millis_ts(s: &str) -> bool {\n    !s.is_empty() && s.chars().all(|c| c.is_ascii_digit())\n}\n// filter rows before use\nlet rows: Vec<_> = raw.iter().filter(|r| valid_millis_ts(&r.funding_rate_timestamp)).collect();","typeGuard":"fn parse_ts(s: &str) -> Option<i64> { s.parse::<i64>().ok() }","tryCatchPattern":"match client.funding_rates(symbol, limit).await {\n    Ok(rates) => rates,\n    Err(e) if e.to_string().contains(\"invalid funding_rate_timestamp\") => {\n        log::warn!(\"malformed funding rate payload: {e}; retrying\");\n        client.funding_rates(symbol, limit).await\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep the Bybit adapter updated to the current API schema","Validate timestamp fields before arithmetic on intervals","Log raw payloads on parse failures to speed diagnosis"],"tags":["rust","bybit","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"}