nautechsystems/nautilus_trader · warning
failed to finish Binance Futures data command tasks: {e}
Error message
failed to finish Binance Futures data command tasks: {e} What it means
During Binance Futures data client shutdown, `finish_tasks` waits for both the session and command task groups to finish (1s/2s timeouts). If the command task group's `finish_shutdown` returns an error, it is collected into a combined message and bailed. This signals command-related WebSocket/subscription tasks did not shut down cleanly.
Source
Thrown at crates/adapters/binance/src/futures/data.rs:336
.finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)),
self.command_tasks
.finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)),
);
let mut errors = Vec::new();
if let Err(e) = session_result {
errors.push(format!(
"failed to finish Binance Futures data session tasks: {e}"
));
}
if let Err(e) = command_result {
errors.push(format!(
"failed to finish Binance Futures data command tasks: {e}"
));
}
if !errors.is_empty() {
anyhow::bail!(errors.join("; "));
}
Ok(())
}
async fn prepare_task_groups(&mut self) -> anyhow::Result<()> {
if !self.session_tasks.is_open() || !self.command_tasks.is_open() {
self.teardown_partial_connect().await?;
self.session_tasks
.start_generation()
.context("failed to start Binance Futures data session task generation")?;
self.command_tasks
.start_generation()
.context("failed to start Binance Futures data command task generation")?;
self.cancellation_token = self.session_tasks.cancellation_token();
}
Ok(())
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Check logs for the paired 'failed to finish Binance Futures data session tasks' message to identify which task group hung
- Ensure the network connection is healthy and the WebSocket close is not blocked by a hung socket before disconnecting
- Avoid overlapping connect/disconnect calls; let the previous shutdown complete
- Retry the disconnect; the teardown sets is_connected=false regardless, so state is consistent
- Upgrade the adapter if timeouts are consistently too short for your latency profile
Example fix
// before client.disconnect(); client.subscribe(cmd); // overlapping work during shutdown // after client.disconnect().await?; // ensure teardown completes first client.subscribe(cmd);
Defensive patterns
Strategy: try-catch
Validate before calling
assert!(session_tasks.is_open() && command_tasks.is_open(), "task groups must be open before disconnect");
Try / catch
match client.disconnect().await {
Err(e) if e.to_string().contains("teardown failed") => log::warn!("task shutdown issue: {e}"),
Err(e) => return Err(e),
Ok(()) => Ok(()),
} Prevention
- Do not overlap connect/disconnect calls
- Ensure network is healthy before disconnecting
- Retry disconnect once on teardown errors
When it happens
Trigger: Calling teardown_partial_connect (from prepare_task_groups, connect, or disconnect) while command tasks (subscription/unsubscription futures) hang or fail to complete within the 1s drain/2s timeout, or the underlying task join fails (e.g. WebSocket already in a broken state).
Common situations: Network partitions during shutdown, disconnect/reconnect races, calling disconnect while subscription commands are still in flight, or repeated connect/disconnect cycles that left task groups in a bad state.
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
- Binance Futures data teardown failed: {}
- failed to finish Binance Spot data command tasks: {e}
- Failed to start Coinbase WebSocket handler task: {e}
- errors.join("; ") (aggregated shutdown errors)
- std::mem::take(&mut self.shutdown_errors).join("; ")
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/821d3883bf1989ce.
Report an issue: GitHub.