nautechsystems/nautilus_trader · error · anyhow::Error

Failed to terminate Binance execution tasks: {e}

Error message

Failed to terminate Binance execution tasks: {e}

What it means

await_pending_tasks shuts down the TaskGroup holding Binance execution (WebSocket/heartbeat) tasks, giving them 1 second to finish and 2 seconds for abort. If finish_shutdown returns an error, the tasks could not be terminated in time and this error wraps the underlying cause.

Source

Thrown at crates/adapters/binance/src/common/execution.rs:57

    }
}

/// Aborts all pending tasks stored in `pending_tasks`.
pub fn abort_pending_tasks(pending_tasks: &TaskGroup) {
    pending_tasks.begin_shutdown();
}

/// Completes bounded shutdown for Binance command tasks.
///
/// # Errors
///
/// Returns an error when bounded task shutdown fails.
pub async fn await_pending_tasks(pending_tasks: &TaskGroup) -> anyhow::Result<()> {
    pending_tasks.begin_shutdown();
    pending_tasks
        .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2))
        .await
        .map_err(|e| anyhow::anyhow!("Failed to terminate Binance execution tasks: {e}"))?;
    Ok(())
}

/// Polls the cache until the account is registered or timeout is reached.
///
/// Each iteration borrows and drops the cache Ref to avoid holding the
/// RefCell borrow across await points, which would block mutable access
/// when the account state is registered by another task.
///
/// # Errors
///
/// Returns an error if the timeout is reached before the account is registered.
pub async fn await_account_registered(
    core: &ExecutionClientCore,
    account_id: AccountId,
    timeout_secs: f64,
) -> anyhow::Result<()> {
    if core.cache().account(&account_id).is_some() {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the wrapped cause ({e}) to identify which task failed to shut down.
  2. Ensure tasks spawned into the TaskGroup respond promptly to cancellation (avoid long blocking calls without cancellation checks).
  3. Increase timeouts if your environment legitimately needs more than the 1s/2s windows.
  4. Retry the shutdown; if persistent, check for deadlocks or stalled network connections and recreate the client.

Example fix

// before
await_pending_tasks(&pending_tasks).await?;

// after
if let Err(e) = await_pending_tasks(&pending_tasks).await {
    tracing::error!("execution task shutdown issue: {e:#}; continuing teardown");
}
Defensive patterns

Strategy: try-catch

Try / catch

// match await_pending_tasks(&pending_tasks).await {
//     Ok(()) => {},
//     Err(e) => tracing::error!("shutdown incomplete: {e:#}") // decide: abort or retry
// }

Prevention

When it happens

Trigger: Disconnecting the Binance execution client while a spawned task (e.g. user-data stream handling, heartbeat polling) is still running and does not complete within the bounded shutdown window (1s graceful + 2s abort).

Common situations: Slow network conditions preventing task cancellation; a task blocked on a long-running HTTP call or a stuck stream read; stopping the node under heavy load; deadlocked task logic that ignores cancellation.

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/0664359865c5d06e. Report an issue: GitHub.