nautechsystems/nautilus_trader · error

No healthy transport clients available

Error message

No healthy transport clients available

What it means

broadcast_cancel collects the transport clients flagged healthy and aborts if none remain, incrementing the failed_cancels metric. This means every BitMEX transport connection is currently unhealthy (disconnected, reconnecting, or failed health checks), so there is no channel over which to send the cancel request.

Source

Thrown at crates/adapters/bitmex/src/broadcast/canceller.rs:639

    /// Returns an error if all cancel requests fail or no healthy clients are available.
    pub async fn broadcast_cancel(
        &self,
        instrument_id: InstrumentId,
        client_order_id: Option<ClientOrderId>,
        venue_order_id: Option<VenueOrderId>,
    ) -> anyhow::Result<Option<OrderStatusReport>> {
        self.total_cancels.fetch_add(1, Ordering::Relaxed);

        let healthy_transports: Vec<TransportClient> = self
            .transports
            .iter()
            .filter(|t| t.is_healthy())
            .cloned()
            .collect();

        if healthy_transports.is_empty() {
            self.failed_cancels.fetch_add(1, Ordering::Relaxed);
            anyhow::bail!("No healthy transport clients available");
        }

        let mut handles = Vec::new();

        for transport in healthy_transports {
            let handle = get_runtime().spawn(async move {
                let client_id = transport.client_id.clone();
                let result = transport
                    .cancel_order(instrument_id, client_order_id, venue_order_id)
                    .await
                    .map(Some); // Wrap success in Some for Option<OrderStatusReport>
                (client_id, result)
            });
            handles.push(handle);
        }

        self.process_cancel_results(
            handles,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check/restore network connectivity and wait for transport reconnect before retrying the cancel
  2. Verify transports are connected and authenticated before submitting/cancelling orders (gate on a connected event)
  3. Inspect health-check and reconnect logic/logs to see why all clients were marked unhealthy
  4. Fall back to the REST cancel endpoint if available
  5. If cancels can fire at startup, add a readiness check or startup delay

Example fix

// before
let result = canceller.broadcast_cancel(&cl_ord_id).await?;
// after
if !transport.is_healthy() {
    transport.wait_until_healthy(timeout).await?; // or fallback to REST cancel
}
let result = canceller.broadcast_cancel(&cl_ord_id).await;
Defensive patterns

Strategy: retry

Validate before calling

// guard before cancelling
if !transports.iter().any(|t| t.is_healthy()) {
    return Err(NoHealthyTransport); // or wait/reconnect first
}

Type guard

fn has_healthy_transport(transports: &[Transport]) -> bool {
    transports.iter().any(|t| t.is_healthy())
}

Try / catch

match canceller.broadcast_cancel(&cl_ord_id).await {
    Err(e) if e.to_string().contains("No healthy transport clients") => {
        wait_for_reconnect(timeout).await?;
        rest_client.cancel_order(&cl_ord_id).await?; // fallback
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling broadcast_cancel(order_id) while all transports report is_healthy() == false — e.g. before the first connection is established, during an outage, or after all clients hit the failure threshold and were marked unhealthy.

Common situations: Network drop or BitMEX outage at the moment a strategy issues a cancel; startup ordering where cancels fire before transports connect; websocket auth failure marking all clients unhealthy; firewalled/restricted network blocking wss://www.bitmex.com.

Related errors


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