nautechsystems/nautilus_trader · error
Betfair data shutdown failed: {}
Error message
Betfair data shutdown failed: {} What it means
When a Betfair data client disconnects or fails during connect, teardown_partial_connect collects errors from shutting down individual tasks/streams into self.shutdown_errors. If any were recorded, teardown bails with this aggregated message so partial-connect failures surface instead of being silently dropped.
Source
Thrown at crates/adapters/betfair/src/data.rs:297
if let Err(e) = self.finish_tasks().await {
self.shutdown_errors.push(e.to_string());
}
self.is_connected.store(false, Ordering::Release);
self.deregister_socket_controls();
if self.stream_client.is_none()
&& self.race_stream_client.is_none()
&& self.cricket_stream_client.is_none()
{
self.stream_shutdowns.lock().clear();
}
if self.shutdown_errors.is_empty() {
Ok(())
} else {
let errors = std::mem::take(&mut self.shutdown_errors);
anyhow::bail!("Betfair data shutdown failed: {}", errors.join("; "))
}
}
fn create_stream_handler(
data_sender: tokio::sync::mpsc::UnboundedSender<DataEvent>,
instruments: Arc<AtomicMap<InstrumentId, InstrumentAny>>,
currency: Currency,
min_notional: Option<Money>,
reconnect_tx: tokio::sync::mpsc::UnboundedSender<()>,
clock: &'static AtomicTime,
) -> StreamMessageHandler {
// Track cumulative traded volumes per (instrument_id, price) to compute
// incremental trade sizes. Betfair `trd` fields report totals, not deltas.
let traded_volumes: Arc<Mutex<AHashMap<(InstrumentId, Decimal), Decimal>>> =
Arc::new(Mutex::new(AHashMap::new()));
let has_initial_connection = Arc::new(AtomicBool::new(false));
Arc::new(move |msg: StreamMessage| {View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the joined error list in the message to identify which task failed and fix the root cause
- Ensure disconnect() is awaited and the runtime is not shutting down mid-await
- Retry connect after a clean disconnect; report if a specific task reliably fails teardown
Defensive patterns
Strategy: try-catch
Try / catch
match client.disconnect().await {
Ok(()) => {},
Err(e) if e.to_string().starts_with("Betfair data shutdown failed") => {
warn!("partial teardown: {e:#}");
}
Err(e) => return Err(e),
} Prevention
- Always await disconnect() on a live tokio runtime before dropping the client
- Avoid cancelling tasks mid-connect; let connect finish or fail first
- Monitor and log shutdown_errors to spot recurring task failures
When it happens
Trigger: disconnect() or a failed connect()/prepare_task_groups path where one or more background tasks (stream reader, heartbeats, subscriptions) fail to cancel/join cleanly, populating shutdown_errors.
Common situations: Network drop mid-connect leaving a task unresponsive; task panics during teardown; calling disconnect while the stream handler is blocked on I/O.
Related errors
- Betfair execution shutdown failed: {}
- Binance Futures data teardown failed: {}
- Polymarket data shutdown failed: {}
- RTDS task owner was dropped
- Polymarket RTDS task owner was dropped
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d91587e284832ded.
Report an issue: GitHub.