nautechsystems/nautilus_trader · error
std::mem::take(&mut self.shutdown_errors).join("; ")
Error message
std::mem::take(&mut self.shutdown_errors).join("; ") What it means
teardown_partial_connect on the Coinbase data client accumulates any errors encountered while disconnecting the WebSocket (and other partial-connect teardown steps) into shutdown_errors, then fails the teardown with all messages joined by '; '. This surfaces why a partially-connected client could not be cleanly rolled back.
Source
Thrown at crates/adapters/coinbase/src/data/mod.rs:334
let (tasks_result, polls_result) =
tokio::join!(self.finish_tasks(), self.deriv_polls.finish_shutdown());
if let Err(e) = tasks_result {
self.shutdown_errors.push(e.to_string());
}
if let Err(e) = polls_result {
self.shutdown_errors.push(e.to_string());
}
if let Err(e) = self.ws_client.disconnect().await {
self.shutdown_errors.push(e.to_string());
}
self.is_connected.store(false, Ordering::Relaxed);
if !self.shutdown_errors.is_empty() {
anyhow::bail!(std::mem::take(&mut self.shutdown_errors).join("; "));
}
Ok(())
}
fn product_id(instrument_id: InstrumentId) -> Ustr {
instrument_id.symbol.inner()
}
// Resolves a caller-supplied product id to Coinbase's canonical alias (if
// any). Coinbase consolidates aliased pairs into a single book server-side
// and rewrites WS subscription confirmations and inbound messages to use
// the canonical id (e.g. BTC-USDC -> BTC-USD), so we must subscribe with
// the canonical id and remember the mapping so inbound messages can be
// re-keyed to what the strategy actually subscribed to.
fn resolve_wire_product_id(&self, subscribed: Ustr) -> Ustr {
self.http_client
.product_aliases()
.get_cloned(&subscribed)View on GitHub (pinned to 18893faf8b)
Solutions
- Read the joined message to identify which teardown step(s) failed (usually the WS disconnect)
- Retry disconnect() once after a short delay; the socket may already be half-closed
- Recreate the client if teardown repeatedly fails — state may be inconsistent after partial connect
- Fix the root cause of the original partial connect that triggered the rollback
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the client is connected before disconnect
if client.is_connected() { client.disconnect().await?; } Try / catch
if let Err(e) = client.disconnect().await {
log::warn!("coinbase teardown failed: {e}; recreating client");
client = rebuild_client().await;
} Prevention
- Fix the root connect failure so the rollback path is rarely taken
- Recreate clients after any teardown error instead of reusing them
- Log full teardown messages — they are '; '-joined multi-error strings
- Avoid concurrent disconnect calls on the same client
When it happens
Trigger: A connect() step fails partway and the rollback path calls ws_client.disconnect().await which itself errors (e.g. socket already closed, network gone), leaving non-empty shutdown_errors.
Common situations: Network drop during a failed connect; calling disconnect() on a client whose WS is already dead; concurrent teardowns racing on the same client.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Binance Spot data teardown failed: {}
- std::mem::take(&mut self.shutdown_errors).join("; ")
- errors joined with "; " (aggregated disconnect errors)
- errors joined with "; " (aggregated disconnect errors)
- {e}; failed to roll back partial Lighter connection: {shutdo
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/34ea590f8c4c3130.
Report an issue: GitHub.