{"record":{"id":"7e70740258f9d0de","repo":"nautechsystems/nautilus_trader","slug":"failed-to-send-pong-e","errorCode":null,"errorMessage":"Failed to send pong: {e}","messagePattern":"Failed to send pong: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/adapters/okx/src/websocket/handler.rs","lineNumber":232,"sourceCode":"        rate_limit_keys: Option<&[Ustr]>,\n    ) -> Result<(), OKXWsError> {\n        let client = self.inner.as_ref().ok_or(OKXWsError::NoActiveClient)?;\n        let connection_epoch = client.connection_epoch();\n        client\n            .send_text_on_connection(payload, rate_limit_keys, connection_epoch)\n            .await\n            .map_err(OKXWsError::TransportSend)\n    }\n\n    pub(super) async fn send_pong(&self) -> anyhow::Result<()> {\n        match self.send_on_connection(TEXT_PONG.to_string(), None).await {\n            Ok(()) => {\n                log::trace!(\"Sent pong response to OKX text ping\");\n                Ok(())\n            }\n            Err(e) => {\n                log::warn!(\"Failed to send pong: error={e}\");\n                Err(anyhow::anyhow!(\"Failed to send pong: {e}\"))\n            }\n        }\n    }\n\n    pub(super) async fn next(&mut self) -> Option<OKXWsMessage> {\n        if let Some(message) = self.pending_messages.pop_front() {\n            return Some(message);\n        }\n\n        let mut poll_raw_next = false;\n\n        loop {\n            if self.signal.load(Ordering::Acquire) {\n                log::debug!(\"Stop signal received\");\n                return None;\n            }\n\n            tokio::select! {","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/websocket/handler.rs#L214-L250","documentation":"OKX sends text `ping` frames on its WebSocket; the handler responds with a pong via the sink. If the send fails (socket closed, backpressure, or send channel dropped), the handler logs a warning and returns this error, which typically triggers reconnect logic because the connection is no longer healthy.","triggerScenarios":"OKX sends a text ping while the underlying WebSocket is closed/broken or the send sink is unavailable, so `send(...)` returns Err in `send_pong`.","commonSituations":"Network interruption mid-session; server closed the connection while a queued ping was being answered; proxy or firewall idle-timeout dropped the socket.","solutions":["Let the error propagate to the reconnect loop and re-establish the connection — the socket is already unusable.","Check network/proxy idle timeouts and enable keep-alive so pings can be answered in time.","Verify the write half of the WebSocket is still shared/alive when the handler runs."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// treat as connection-lost: trigger reconnect\nif let Err(e) = handler_result {\n    log::warn!(\"ws unhealthy: {e}; reconnecting\");\n    reconnect_with_backoff().await;\n}","preventionTips":["Configure proxy/firewall idle timeouts longer than OKX's ping interval.","Ensure the network is stable; pongs failing implies the socket is already broken.","Monitor logs for repeated pong failures as an early disconnect signal."],"tags":["websocket","okx","ping-pong","keepalive"],"backgroundTag":"broken-pipe","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"}