nautechsystems/nautilus_trader · error
data-connect timeout
Error message
data-connect timeout
What it means
connect_data_phase wraps self.kernel.connect_data_clients() in a timeout bounded by the remaining time until the shared connection deadline. If connecting all data clients does not finish in time, the future is cancelled and this error is returned; start() then aborts startup with "Data client connection timed out". A zero timeout_connection is intentionally still allowed (fails-closed-on-poll semantics), so this only fires when a real connect hangs or the budget is exhausted.
Source
Thrown at crates/live/src/node/mod.rs:2100
};
AsyncRunner::handle_exec_event(evt);
if let Some(fill) = &recent_fill_candidate {
self.exec_manager.commit_recent_fill_if_applied(fill);
}
}
async fn connect_data_phase(&mut self, deadline: dst::time::Instant) -> anyhow::Result<()> {
// A zero remaining budget still admits an immediately-ready connect (an
// empty/ready client set completes on the first poll); a pending connect
// fails closed on that same poll. This keeps a zero `timeout_connection`
// - a supported "do not wait, but allow ready work" configuration -
// working, while still bounding a hung connect.
let remaining = deadline.saturating_duration_since(dst::time::Instant::now());
dst::time::timeout(remaining, self.kernel.connect_data_clients())
.await
.map_err(|_| anyhow::anyhow!("data-connect timeout"))
}
async fn connect_exec_clients(&mut self, deadline: dst::time::Instant) -> anyhow::Result<()> {
let remaining = deadline.saturating_duration_since(dst::time::Instant::now());
dst::time::timeout(remaining, self.kernel.connect_exec_clients())
.await
.map_err(|_| anyhow::anyhow!("exec-connect timeout"))
}
/// Connects execution clients and checks all engines are connected.
///
/// Returns the final connection wait status.
/// Must be called after data clients are connected and instrument events drained.
async fn connect_exec_phase(
&mut self,
deadline: dst::time::Instant,
) -> anyhow::Result<EngineConnectionStatus> {
self.connect_exec_clients(deadline).await?;View on GitHub (pinned to 18893faf8b)
Solutions
- Increase timeout_connection to comfortably cover data client connects plus instrument event draining.
- Verify market-data endpoint reachability and credentials; fix any adapter-level connect error surfaced in logs.
- Reduce the number or cost of initial subscriptions if venue onboarding is slow.
- Check DNS/proxy configuration on the host that could stall TCP/TLS establishment.
Example fix
// before timeout_connection: Duration::from_secs(15) // after timeout_connection: Duration::from_secs(120)
Defensive patterns
Strategy: retry
Validate before calling
// Ensure the shared connection deadline can cover data connect let deadline_needed = expected_data_connect_secs + instrument_drain_secs; assert!(config.timeout_connection.as_secs() >= deadline_needed);
Try / catch
match node.start().await {
Err(e) if e.to_string().contains("data-connect timeout") => {
// raise timeout_connection / check market-data endpoints, then retry
}
other => other?,
} Prevention
- Budget timeout_connection for both data and exec phases plus instrument draining
- Verify market-data endpoint reachability before startup
- Limit initial subscription fan-out on slow venues
- Fix DNS/proxy stalls on the host
When it happens
Trigger: dst::time::timeout(remaining, connect_data_clients()) elapses in connect_data_phase (mod.rs:2096-2101); remaining is deadline.saturating_duration_since(now), so earlier startup phases may have already consumed the deadline.
Common situations: Slow market-data venue handshakes; instrument subscription floods taking longer than timeout_connection; DNS or TLS stalls; the exec/data phase ordering consuming the shared deadline so data connect gets little time on retry paths.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- readiness timeout while waiting for engine connections
- exec-connect timeout
- Timeout waiting for account {account_id} to be registered af
- subscription confirmation failed: {e}
- Lighter WebSocket initial connection timeout after {} second
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7d6232d10c9a23d4.
Report an issue: GitHub.