nautechsystems/nautilus_trader · error

Failed to terminate Betfair execution tasks: {e}

Error message

Failed to terminate Betfair execution tasks: {e}

What it means

await_pending_tasks shuts down the Betfair execution client's pending-task group via begin_shutdown/finish_shutdown with 1s and 2s grace durations. If finish_shutdown cannot terminate the tasks within those windows or returns an error, it is wrapped in this anyhow error.

Source

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

        self.reconciliation_gate.clear();
    }

    fn abort_pending_tasks(&self) {
        self.pending_tasks.begin_shutdown();
    }

    fn abort_session_tasks(&mut self) {
        self.session_tasks.begin_shutdown();
        self.account_refresh_tx = None;
    }

    async fn await_pending_tasks(&self) -> anyhow::Result<()> {
        self.pending_tasks.begin_shutdown();
        self.pending_tasks
            .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))
            .await
            .map_err(|e| anyhow::anyhow!("Failed to terminate Betfair execution tasks: {e}"))?;
        Ok(())
    }

    async fn await_session_tasks(&self) -> anyhow::Result<()> {
        self.session_tasks.begin_shutdown();
        self.session_tasks
            .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))
            .await
            .map_err(|e| anyhow::anyhow!("Failed to terminate Betfair session tasks: {e}"))?;
        Ok(())
    }

    async fn teardown_partial_connect(&mut self) -> anyhow::Result<()> {
        self.abort_session_tasks();
        self.abort_pending_tasks();

        if let Some(control) = &self.socket_control {
            control.deregister();

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Increase the shutdown grace/timeout durations if legitimate in-flight work is common
  2. Drain or cancel long-running requests before calling await_pending_tasks
  3. Check network/API health; the root cause is usually tasks blocked on unresponsive Betfair endpoints

Example fix

// before
self.pending_tasks.finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)).await?;
// after
self.pending_tasks.finish_shutdown(Duration::from_secs(5), Duration::from_secs(10)).await?;
Defensive patterns

Strategy: try-catch

Validate before calling

// check no order tasks in flight before shutdown
if !self.pending_tasks.is_idle() { log::warn!("tasks still in flight at shutdown"); }

Try / catch

if let Err(e) = exec_client.await_pending_tasks().await {
    log::error!("pending task shutdown: {e}; forcing teardown");
    exec_client.abort_pending_tasks();
}

Prevention

When it happens

Trigger: In-flight HTTP order/account tasks not completing within the 1s grace + 2s timeout windows during teardown; tasks stuck awaiting unresponsive Betfair API responses.

Common situations: Disconnecting while Betfair API is slow or hung; network outage at shutdown; placing orders immediately before disconnect so tasks are still in flight.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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