nautechsystems/nautilus_trader · error

Bybit data shutdown failed

Error message

Bybit data shutdown failed: {}

What it means

teardown_partial_connect rolls back a partially completed Bybit data client connect: it stops tasks, closes sessions, and collects shutdown_errors. If any errors occurred while tearing down, it bails with all of them joined. This surfaces secondary failures that occurred while recovering from a failed connect.

Solutions

  1. Fix the primary connect failure first (network, API credentials, region blocking)
  2. Check Bybit status and connectivity before retrying
  3. Retry connect after backoff; shutdown_errors are drained so a clean retry is safe
  4. If cleanup errors persist on a healthy network, report with full logs
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: verify API reachability and credentials before connect
assert!(bybit_reachable().await, "Bybit API unreachable");

Try / catch

loop {
    match client.connect().await {
        Ok(()) => break,
        Err(e) if attempts < MAX => { log::warn!("retrying after partial teardown: {e:#}"); attempts += 1; backoff(); }
        Err(e) => return Err(e),
    }
}

Prevention

When it happens

Trigger: A connect attempt fails partway (e.g. session or command task startup fails) and cleanup itself encounters errors — such as failing to abort tasks or close websocket sessions — producing non-empty shutdown_errors.

Common situations: Unstable network during connect causing both startup failure and messy cleanup; exchange refusing connections so multiple subsystems error during rollback; calling connect repeatedly during an outage.

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/e1d49a574bf7f426. Report an issue: GitHub.

Appendix: source

Thrown at crates/adapters/bybit/src/data.rs:422

            ws_client.begin_shutdown();
        }

        for ws_client in &mut self.ws_clients {
            if let Err(e) = ws_client.close().await {
                self.shutdown_errors.push(e.to_string());
            }
        }

        if let Err(e) = self.finish_tasks().await {
            self.shutdown_errors.push(e.to_string());
        }
        self.is_connected.store(false, Ordering::Release);

        if self.shutdown_errors.is_empty() {
            Ok(())
        } else {
            let errors = std::mem::take(&mut self.shutdown_errors);
            anyhow::bail!("Bybit data shutdown failed: {}", errors.join("; "))
        }
    }
}

fn send_data(sender: &tokio::sync::mpsc::UnboundedSender<DataEvent>, data: Data) {
    if let Err(e) = sender.send(DataEvent::Data(data)) {
        log::error!("Failed to emit data event: {e}");
    }
}

fn validate_orderbook_depth(depth: u32) -> anyhow::Result<()> {
    if !BYBIT_BOOK_DEPTHS.contains(&depth) {
        anyhow::bail!("invalid depth {depth}; valid values are {BYBIT_BOOK_DEPTHS:?}");
    }

    Ok(())
}

View on GitHub (pinned to 18893faf8b)