nautechsystems/nautilus_trader · error · anyhow::Error

Failed to terminate Binance Futures session tasks: {e}

Error message

Failed to terminate Binance Futures session tasks: {e}

What it means

During disconnect/shutdown, await_session_tasks calls finish_session_tasks to shut down the WebSocket session tasks; if shutdown completes with an error (TaskShutdownError, e.g. tasks not stopping within the timeout), it is wrapped in this anyhow error. It signals the Binance Futures data/execution client could not cleanly terminate its session tasks.

Source

Thrown at crates/adapters/binance/src/futures/execution.rs:916

    {
        crate::common::execution::spawn_task(&self.pending_tasks, description, fut);
    }

    fn abort_pending_tasks(&self) {
        crate::common::execution::abort_pending_tasks(&self.pending_tasks);
    }

    fn abort_session_tasks(&self) {
        self.session_tasks.begin_shutdown();
    }

    async fn await_pending_tasks(&self) -> anyhow::Result<()> {
        crate::common::execution::await_pending_tasks(&self.pending_tasks).await
    }

    async fn await_session_tasks(&self) -> anyhow::Result<()> {
        self.finish_session_tasks().await.map_err(|e| {
            anyhow::anyhow!("Failed to terminate Binance Futures session tasks: {e}")
        })?;
        Ok(())
    }

    async fn finish_session_tasks(&self) -> Result<(), TaskShutdownError> {
        self.session_tasks.begin_shutdown();
        self.session_tasks
            .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))
            .await?;
        Ok(())
    }

    async fn await_dispatch_task(&self) -> anyhow::Result<()> {
        let _recovery_guard = self.recovery_lock.lock().await;
        let mut task_slot = self.ws_task.lock().await;
        let Some(outcome) = finish_task(
            &mut task_slot,
            Duration::from_secs(1),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Retry the disconnect; transient stalls often resolve once the network recovers
  2. Check network/proxy stability that may keep WebSocket reads blocked past the shutdown timeout
  3. Upgrade to the latest nautilus_trader version for shutdown-timeout fixes
  4. Capture and inspect the inner TaskShutdownError via the error chain to see which task failed to stop
  5. Force-drop the node/kernel as a last resort if tasks are wedged

Example fix

// before
client.disconnect().await?; // may surface 'Failed to terminate Binance Futures session tasks'
// after
if let Err(e) = client.disconnect().await {
    tracing::warn!("session task shutdown failed: {e:#}; retrying");
    client.disconnect().await?;
}
Defensive patterns

Strategy: try-catch

Try / catch

match client.disconnect().await {
    Err(e) if e.to_string().contains("Failed to terminate Binance Futures session tasks") => {
        tracing::warn!("graceful shutdown failed: {e:#}; retrying");
        client.disconnect().await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling disconnect (or connect's failure path) while session tasks are stuck — e.g. a WebSocket stream task blocked on a hung network read or a handler not honoring the shutdown signal — causing finish_session_tasks to time out or fail.

Common situations: Network partitions leaving WS reads blocked, slow/stalled event loop under load, or a bug in a task that ignores abort signals during node shutdown.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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