{"record":{"id":"54d8a7438443da3a","repo":"nautechsystems/nautilus_trader","slug":"errors-join-54d8a7","errorCode":null,"errorMessage":"errors.join(\"; \")","messagePattern":"errors\\.join\\(\"; \"\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/data.rs","lineNumber":1176,"sourceCode":"        self.is_connected.store(false, Ordering::Release);\n\n        let mut errors = Vec::new();\n        if let Err(e) = task_result {\n            errors.push(e.to_string());\n        }\n\n        if let Err(e) = public_result {\n            errors.push(e.to_string());\n        }\n\n        if let Err(e) = business_result {\n            errors.push(e.to_string());\n        }\n\n        if errors.is_empty() {\n            Ok(())\n        } else {\n            anyhow::bail!(errors.join(\"; \"))\n        }\n    }\n}\n\nfn handle_book_sequence_outcome(\n    outcome: BookSequenceOutcome,\n    instrument_id: InstrumentId,\n    book_channels: &Arc<AtomicMap<InstrumentId, OKXBookChannel>>,\n    book_sync: &BookSyncTracker,\n    recovery_ws: Option<&OKXWebSocketClient>,\n    snapshot_timeout: Duration,\n    tasks: &TaskSpawner,\n) -> bool {\n    match outcome {\n        BookSequenceOutcome::Accept => true,\n        BookSequenceOutcome::Suppress => false,\n        BookSequenceOutcome::Recover {\n            last_seq_id,","sourceCodeStart":1158,"sourceCodeEnd":1194,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/data.rs#L1158-L1194","documentation":"teardown_transports collects the error message of every individual transport teardown failure and, if any occurred, aborts with a single error whose message is all failures joined with \"; \". This error surfaces when one or more OKX websocket/HTTP transports failed to shut down cleanly during connect_session, connect, or disconnect.","triggerScenarios":"Calling connect, connect_session, or disconnect on the OKX data client when at least one transport's teardown (e.g. closing a websocket, cancelling a stream task, joining a handle) returns an Err; all collected messages are joined and bailed.","commonSituations":"Network partitions during shutdown causing websocket close timeouts; tasks already aborted/panicked so joining fails; calling disconnect while transports are mid-reconnect; runtime shutdown racing transport lifecycles.","solutions":["Read the joined message to identify which transports failed and fix the root cause of each underlying error (usually a network or task-join issue)","Retry disconnect after a short delay — teardown failures during a network partition often resolve once connectivity returns","Ensure disconnect is not called concurrently with reconnect logic; serialize connection lifecycle calls","If a task was already finished, tolerate AlreadyClosed-style teardown errors by logging instead of failing shutdown"],"exampleFix":"// before\nclient.disconnect().await?; // bails with joined teardown errors\n// after\nif let Err(e) = client.disconnect().await {\n    log::warn!(\"teardown reported failures (may be benign on shutdown): {e}\");\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = client.disconnect().await {\n    log::warn!(\"transport teardown reported failures: {e}\"); // joined per-transport messages\n    // inspect individual messages before deciding to retry or escalate\n}","preventionTips":["Do not call disconnect concurrently with reconnect logic","Retry teardown after transient network failures","Monitor joined messages for recurring per-transport failures","Ensure transport tasks are not aborted externally before disconnect"],"tags":["okx","transport","shutdown","websocket"],"backgroundTag":"connection-refused","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"}