{"record":{"id":"77a7cf9cfc501a6d","repo":"nautechsystems/nautilus_trader","slug":"failed-to-send-message-e","errorCode":null,"errorMessage":"Failed to send message: {e}","messagePattern":"Failed to send message: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/websocket/streams/handler.rs","lineNumber":297,"sourceCode":"            self.pending_requests.take(request_id);\n            return Err(e);\n        }\n\n        Ok(())\n    }\n\n    async fn send_text(\n        &self,\n        payload: String,\n        rate_limit_keys: Option<&[Ustr]>,\n    ) -> anyhow::Result<()> {\n        let Some(client) = &self.inner else {\n            anyhow::bail!(\"No active WebSocket client\");\n        };\n        client\n            .send_text(payload, rate_limit_keys)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to send message: {e}\"))?;\n        Ok(())\n    }\n}\n\n/// Classifies a JSON text frame that did not match a subscription response or\n/// known error envelope. Recognizes the `serverShutdown` event; otherwise\n/// emits `RawJson` for parseable payloads or an empty vector for garbage.\nfn classify_unsolicited_json(text: &str) -> Vec<BinanceSpotWsMessage> {\n    let Ok(value) = serde_json::from_str::<serde_json::Value>(text) else {\n        log::warn!(\"Failed to parse JSON message: {text}\");\n        return vec![];\n    };\n\n    if value.get(\"e\").and_then(|v| v.as_str()) == Some(\"serverShutdown\")\n        && let Ok(msg) = serde_json::from_value::<BinanceSpotServerShutdownMsg>(value.clone())\n    {\n        log::warn!(\n            \"Binance server shutdown notice received (event_time={}); disconnect expected ~10 minutes from event\",","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/websocket/streams/handler.rs#L279-L315","documentation":"The WebSocket handler could not deliver a text message (subscribe/unsubscribe control frame) through the active Binance Spot stream connection. `send_text` on the inner client failed with the underlying error `{e}` (connection closed, rate limiter rejection, backpressure, etc.).","triggerScenarios":"`handle_subscribe` or `handle_unsubscribe` builds a subscription payload and calls `send_text` while the connection is being closed or saturated; the inner `client.send_text(payload, rate_limit_keys).await` returns `Err(e)` which is wrapped into this error.","commonSituations":"WebSocket dropped mid-session (network blip, server shutdown) and a subscribe is still pending; exceeding Binance message rate limits; trying to send before the connection handshake finished despite `inner` being set.","solutions":["Check the underlying `{e}`: for a closed connection, reconnect the stream client and re-issue the subscription.","Verify rate-limit configuration (`rate_limit_keys`) — reduce subscription churn or increase limits if the send was throttled.","Ensure the WebSocket connection is established and healthy before calling subscribe/unsubscribe.","Add retry/backoff around send for transient errors and monitor the stream's reconnect lifecycle."],"exampleFix":"// before: fire-and-forget subscribe, error aborts handler\nclient.send_text(payload, keys).await?;\n// after: tolerate transient failure, allow reconnect logic to resubscribe\nmatch client.send_text(payload, keys).await {\n    Ok(()) => Ok(()),\n    Err(e) => { warn!(\"send failed, will resubscribe after reconnect: {e}\"); Ok(()) }\n}","handlingStrategy":"retry","validationCode":"if stream_client.connection_state() != ConnectionState::Active {\n    return Err(anyhow::anyhow!(\"cannot send: websocket not active\"));\n}","typeGuard":null,"tryCatchPattern":"match client.send_text(payload, keys).await {\n    Ok(()) => Ok(()),\n    Err(e) if is_connection_closed(&e) => {\n        stream_client.reconnect().await?;\n        client.send_text(payload, keys).await\n            .map_err(|e| anyhow::anyhow!(\"Failed to send message: {e}\"))\n    }\n    Err(e) => Err(anyhow::anyhow!(\"Failed to send message: {e}\")),\n}","preventionTips":["Track connection lifecycle and re-issue subscriptions after every reconnect.","Add exponential backoff on send failures.","Keep subscription traffic within Binance message rate limits."],"tags":["network","websocket","send","binance","rust"],"backgroundTag":"web-socket-send-failed","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"}