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
- Read the aggregated errors to find the offending task and address its root cause
- Await disconnect() to completion on a live runtime before dropping the client
- 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
- Gracefully stop the execution client before runtime shutdown
- Reconnect after full disconnect rather than reusing a partially connected client
- Capture per-task logs to identify which handler fails teardown
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
- Betfair data shutdown failed: {}
- std::mem::take(&mut self.shutdown_errors).join("; ")
- Bybit execution shutdown failed: {}
- Failed to terminate Lighter tasks: {}
- Polymarket data shutdown failed: {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8f4ae7a4ab5e42ca.
Report an issue: GitHub.