nautechsystems/nautilus_trader · error

Failed to register Betfair keep-alive task: {e}

Error message

Failed to register Betfair keep-alive task: {e}

What it means

During BetfairMarketDataClient::connect, a background keep-alive task is spawned to periodically re-send the keepAlive message and prevent the Betfair session from expiring. If the task registration itself fails (e.g. the runtime/task registry rejects the spawn), connect returns this anyhow error and the whole connect sequence fails.

Source

Thrown at crates/adapters/betfair/src/data.rs:1031

                            }
                        };

                        let _ = keep_alive_client
                            .with_session_token(|token| {
                                refresh_stream_sessions(
                                    keep_alive_stream.as_ref(),
                                    keep_alive_race_stream.as_deref(),
                                    keep_alive_cricket_stream.as_deref(),
                                    &keep_alive_app_key,
                                    token,
                                    session_replaced,
                                );
                            })
                            .await;
                        log::debug!("Betfair session keep-alive sent");
                    }
                })
                .map_err(|e| anyhow::anyhow!("Failed to register Betfair keep-alive task: {e}"))?;

            let reconnect_http = Arc::clone(&self.http_client);
            let reconnect_stream = Arc::clone(self.stream_client.as_ref().unwrap());
            let reconnect_race_stream = self.race_stream_client.as_ref().map(Arc::clone);
            let reconnect_cricket_stream = self.cricket_stream_client.as_ref().map(Arc::clone);
            let reconnect_app_key = self.credential.app_key().to_string();

            self.session_tasks
                .spawn(async move {
                    while reconnect_rx.recv().await.is_some() {
                        log::info!("Handling data stream reconnection");

                        let session_replaced = match reconnect_http.keep_alive_with_token().await {
                            Ok(_) => false,
                            Err(ref e) if e.is_login_failed() => {
                                log::warn!(
                                    "Session expired on reconnect, attempting re-login: {e}"
                                );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Retry connect when the runtime is fully running, not during shutdown
  2. Ensure connect is called on a live multi-threaded tokio runtime and never concurrently with disconnect/teardown
  3. Inspect the inner error `e` in the message for the root registration failure

Example fix

// before: connect called during app shutdown
market_client.connect().await?;
// after: connect only while the runtime is healthy
assert!(!shutting_down.load(Ordering::SeqCst));
market_client.connect().await?;
Defensive patterns

Strategy: retry

When it happens

Trigger: The keep-alive task registration future returns Err while connect is running — e.g. the tokio runtime is shutting down, the registration channel is closed, or the underlying task-generation registry refuses a new task after shutdown was begun.

Common situations: Connecting during adapter teardown or executor shutdown; nested runtimes or blocking a runtime thread so the registration future cannot complete; calling connect concurrently with disconnect.

Related errors


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