{"record":{"id":"bea6a4faad52b44a","repo":"nautechsystems/nautilus_trader","slug":"e-bea6a4","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/architect_ax/src/data.rs","lineNumber":307,"sourceCode":"        clippy::unnecessary_wraps,\n        reason = \"callers forward Result to trait methods\"\n    )]\n    fn ws_symbol_op<F, Fut>(\n        &self,\n        instrument_id: InstrumentId,\n        op: F,\n        context: &'static str,\n    ) -> anyhow::Result<()>\n    where\n        F: FnOnce(AxMdWebSocketClient, String) -> Fut + Send + 'static,\n        Fut: Future<Output = Result<(), AxWsClientError>> + Send,\n    {\n        let symbol = instrument_id.symbol.to_string();\n        log::debug!(\"{context} for {symbol}\");\n\n        let ws = self.ws_client.clone();\n        self.spawn_ws(\n            async move { op(ws, symbol).await.map_err(|e| anyhow::anyhow!(e)) },\n            context,\n        );\n\n        Ok(())\n    }\n\n    fn spawn_ws<F>(&self, fut: F, context: &'static str)\n    where\n        F: Future<Output = anyhow::Result<()>> + Send + 'static,\n    {\n        let future = async move {\n            if let Err(e) = fut.await {\n                log::error!(\"{context}: {e:?}\");\n            }\n        };\n\n        if let Err(e) = self.pending_tasks.spawn(future) {\n            log::warn!(\"Skipping AX {context} after shutdown began: {e}\");","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/architect_ax/src/data.rs#L289-L325","documentation":"ws_symbol_op runs a per-symbol websocket operation (subscribe/unsubscribe) and maps any error from the underlying WS call into an anyhow error via anyhow::anyhow!(e), which spawn_ws then propagates. The message is the inner error's display text, so it surfaces whatever the websocket operation failed with.","triggerScenarios":"Any of subscribe_quotes, subscribe_trades, subscribe_mark_prices, subscribe_instrument_status, unsubscribe_book_deltas, or unsubscribe_quotes when the underlying ws op fails — e.g. the websocket is disconnected, the symbol is rejected by AX, or the send times out.","commonSituations":"Calling subscribe before connect completes or after disconnect; subscribing to an unsupported/invalid symbol; network drop mid-subscription; AX rejecting an unparseable symbol string.","solutions":["Ensure the data client is connected before subscribing (check is_connected / await connect)","Verify the instrument_id symbol is valid on AX and matches AX symbol conventions","Retry the subscription; check the inner error text for the root cause (auth, network, symbol)","Inspect ws client logs for the underlying transport failure"],"exampleFix":"// before\nclient.subscribe_quotes(instrument_id)?;\n// after\nif !client.is_connected().await { client.connect().await?; }\nclient.subscribe_quotes(instrument_id)?;","handlingStrategy":"retry","validationCode":"// Rust\nif !client.is_connected().await { client.connect().await?; }\n// validate symbol exists on AX before subscribing","typeGuard":null,"tryCatchPattern":"// Rust\nfor attempt in 0..3 {\n    match client.subscribe_quotes(instrument_id).await {\n        Ok(()) => break,\n        Err(e) if attempt < 2 => tokio::time::sleep(backoff(attempt)).await,\n        Err(e) => return Err(e),\n    }\n}","preventionTips":["Always connect before subscribing or unsubscribing","Validate instrument IDs against the AX symbol format before subscribing","Retry subscriptions with backoff; WS blips are common","Read the inner error text — ws_symbol_op re-wraps the underlying failure verbatim"],"tags":["websocket","subscription","network"],"backgroundTag":"network-request-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}