{"record":{"id":"a4d51bd0c3eeef09","repo":"nautechsystems/nautilus_trader","slug":"failed-to-send-subscription-after-retries-e","errorCode":null,"errorMessage":"Failed to send subscription after retries: {e}","messagePattern":"Failed to send subscription after retries: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/websocket/handler.rs","lineNumber":542,"sourceCode":"        for arg in &args {\n            log::debug!(\n                \"Subscribing to channel: channel={:?}, inst_id={:?}\",\n                arg.channel,\n                arg.inst_id\n            );\n        }\n\n        let message = OKXSubscription {\n            op: OKXWsOperation::Subscribe,\n            args,\n        };\n\n        let json_txt = serde_json::to_string(&message)\n            .map_err(|e| anyhow::anyhow!(\"Failed to serialize subscription: {e}\"))?;\n\n        self.send_with_retry(json_txt, Some(OKX_RATE_LIMIT_KEY_SUBSCRIPTION.as_slice()))\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to send subscription after retries: {e}\"))?;\n        Ok(())\n    }\n\n    async fn handle_unsubscribe(&self, args: Vec<OKXSubscriptionArg>) -> anyhow::Result<()> {\n        for arg in &args {\n            log::debug!(\n                \"Unsubscribing from channel: channel={:?}, inst_id={:?}\",\n                arg.channel,\n                arg.inst_id\n            );\n        }\n\n        let message = OKXSubscription {\n            op: OKXWsOperation::Unsubscribe,\n            args,\n        };\n\n        let json_txt = serde_json::to_string(&message)","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/websocket/handler.rs#L524-L560","documentation":"After serializing the subscribe message, `handle_subscribe` sends it via `send_with_retry` under the OKX subscription rate-limit key. If all retry attempts fail (connection down, rate limit sustained, sink closed), the error is wrapped with this message and the subscription does not take effect.","triggerScenarios":"Subscribing to a channel while the WebSocket is disconnected, or repeated sends fail within the retry window due to OKX rate limits or a broken socket.","commonSituations":"Subscribing immediately after connect before the socket is fully established; subscribing to too many channels at once hitting OKX's subscription rate limit; network drop during subscribe.","solutions":["Retry the subscription after reconnecting; most adapters resubscribe on reconnect — verify the connection is active first.","Reduce subscribe burst size or add spacing to stay under OKX's subscription rate limits.","Inspect the inner `{e}` to distinguish rate-limit errors from transport errors."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// rust\nif let Err(e) = subscribe(arg).await {\n    if e.to_string().contains(\"after retries\") {\n        tokio::time::sleep(Duration::from_secs(1)).await;\n        subscribe(arg).await?; // or wait for adapter's resubscribe-on-reconnect\n    }\n}","preventionTips":["Wait for the connection to be fully active before subscribing.","Space out subscription batches to respect OKX rate limits.","Rely on resubscribe-on-reconnect behavior for transient drops."],"tags":["websocket","okx","subscribe","rate-limit","retry"],"backgroundTag":"rate-limit-exceeded","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"}