nautechsystems/nautilus_trader · error

joined shutdown errors (std::mem::take(&mut self.shutdown_er

Error message

joined shutdown errors (std::mem::take(&mut self.shutdown_errors).join("; "))

What it means

Raised by `teardown_partial_connect` in the Derive data client when one or more pending connection tasks failed during teardown. Each failure string is accumulated in `shutdown_errors`, then all errors are joined with "; " and returned as a single aggregated error once the teardown completes.

Source

Thrown at crates/adapters/derive/src/data.rs:271

            self.shutdown_errors
                .push(format!("Derive WebSocket shutdown failed: {e}"));
        }
        let (session_result, pending_result) =
            tokio::join!(self.join_session_tasks(), self.join_pending_tasks());
        self.clear_subscription_state();
        self.channel_subscriptions.clear_transitions();
        self.is_connected.store(false, Ordering::Release);

        if let Err(e) = session_result {
            self.shutdown_errors.push(e.to_string());
        }

        if let Err(e) = pending_result {
            self.shutdown_errors.push(e.to_string());
        }

        if !self.shutdown_errors.is_empty() {
            anyhow::bail!(std::mem::take(&mut self.shutdown_errors).join("; "));
        }
        Ok(())
    }

    fn spawn_stream_task(
        &self,
        mut rx: tokio::sync::mpsc::UnboundedReceiver<DeriveWsMessage>,
    ) -> anyhow::Result<()> {
        let ctx = WsMessageContext {
            clock: self.clock,
            data_sender: self.data_sender.clone(),
            instruments: Arc::clone(&self.instruments),
            active_book_delta_channels: Arc::clone(&self.active_book_delta_channels),
            active_book_depth10_channels: Arc::clone(&self.active_book_depth10_channels),
            active_ticker_channels: Arc::clone(&self.active_ticker_channels),
            active_quote_subs: Arc::clone(&self.active_quote_subs),
            active_trade_subs: Arc::clone(&self.active_trade_subs),
            active_mark_subs: Arc::clone(&self.active_mark_subs),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the joined messages in the error to identify which underlying task(s) failed and fix the root cause (network, auth, URL).
  2. Check connectivity and Derive API availability, then retry connect().
  3. Verify credentials/API URL configuration if the underlying errors mention auth or request failures.
  4. Retry the disconnect()/connect() cycle; the error list is cleared via mem::take so a clean retry is possible.

Example fix

null
Defensive patterns

Strategy: try-catch

Try / catch

match client.connect().await {
    Ok(()) => {},
    Err(e) => {
        // e may contain multiple causes joined by "; " — log all, retry after backoff
        log::error!("Derive connect teardown errors: {e}");
        tokio::time::sleep(BACKOFF).await;
        retry_connect();
    }
}

Prevention

When it happens

Trigger: Calling connect() or disconnect() when spawned subscription/stream tasks fail to complete or error out while being awaited during partial-connection cleanup (e.g. a WebSocket task panicked, errored, or the HTTP init step failed mid-connect).

Common situations: Network outages or Derive API unavailability while connecting; auth failures mid-handshake leaving tasks to fail; disconnecting while streams are in an error state; seeing multiple underlying causes joined in one message.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/bde54aeb7b065b1d. Report an issue: GitHub.