nautechsystems/nautilus_trader · error

Betfair execution shutdown failed: {}

Error message

Betfair execution shutdown failed: {}

What it means

Analogous to the data client: teardown_partial_connect in the Betfair execution client aggregates errors from cancelling/joining its tasks (order streams, handlers) and bails with this message when teardown of a partially connected client produced any errors.

Source

Thrown at crates/adapters/betfair/src/execution.rs:575

        self.http_client.disconnect().await;
        let (session_result, pending_result) =
            tokio::join!(self.await_session_tasks(), self.await_pending_tasks());
        self.core.set_disconnected();
        self.clear_resync_state();

        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() {
            Ok(())
        } else {
            let errors = std::mem::take(&mut self.shutdown_errors);
            anyhow::bail!("Betfair execution shutdown failed: {}", errors.join("; "))
        }
    }

    #[expect(clippy::too_many_arguments)]
    fn create_ocm_handler(
        emitter: ExecutionEventEmitter,
        account_id: AccountId,
        currency: Currency,
        ocm_state: Arc<Mutex<OcmState>>,
        data_sender: tokio::sync::mpsc::UnboundedSender<DataEvent>,
        market_ids_filter: Option<ahash::AHashSet<String>>,
        ignore_external_orders: bool,
        reconnect_tx: tokio::sync::mpsc::UnboundedSender<u64>,
        queued_generation: Arc<AtomicU64>,
        pending_resync: Arc<AtomicBool>,
        reconciliation_gate: Arc<ReconciliationGate>,
        replay_buffer: Arc<Mutex<Vec<ReceivedOcm>>>,
        account_refresh_tx: tokio::sync::mpsc::UnboundedSender<()>,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the aggregated errors to find the offending task and address its root cause
  2. Await disconnect() to completion on a live runtime before dropping the client
  3. Retry the connect cycle; if persistent, capture logs of the failing task
Defensive patterns

Strategy: try-catch

Try / catch

match exec_client.disconnect().await {
    Err(e) if e.to_string().contains("shutdown failed") => warn!("teardown issues: {e:#}"),
    other => other?,
}

Prevention

When it happens

Trigger: connect() failure or disconnect() where execution-client background tasks fail to shut down cleanly, appending entries to shutdown_errors.

Common situations: TLS/stream failure during connect leaving the order stream task alive; disconnect raced with an in-flight order stream message; runtime dropped before tasks finished.

Related errors


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