nautechsystems/nautilus_trader · error · anyhow::Error

Failed to connect after {max_attempts} attempts

Error message

Failed to connect after {max_attempts} attempts

What it means

connect_with_retry in the Interactive Brokers connection manager gives up after exhausting the configured attempt budget: when retry_indefinitely is false and the attempt counter exceeds max_attempts, it bails with this error. It signals that the TWS/IB Gateway socket could not be established within the allowed retries, aborting the connection attempt.

Source

Thrown at crates/adapters/interactive_brokers/src/common/connection.rs:99

    ///
    /// # Returns
    ///
    /// Returns the connected client on success.
    ///
    /// # Errors
    ///
    /// Returns an error if connection fails after max attempts.
    pub async fn connect_with_retry(&self) -> anyhow::Result<Arc<Client>> {
        const MAX_BACKOFF: Duration = Duration::from_secs(60);
        let mut attempt = 0;
        let mut backoff = Duration::from_secs(1);

        loop {
            attempt += 1;
            self.attempt_count.store(attempt, Ordering::Relaxed);

            if !self.retry_indefinitely && attempt > self.max_attempts {
                anyhow::bail!("Failed to connect after {} attempts", self.max_attempts);
            }

            tracing::debug!(
                "Connection attempt {} to {}:{} (client_id: {})",
                attempt,
                self.host,
                self.port,
                self.client_id
            );

            let address = format!("{}:{}", self.host, self.port);
            match Client::connect(&address, self.client_id).await {
                Ok(client) => {
                    tracing::info!(
                        "Successfully connected to IB Gateway/TWS at {} (client_id: {})",
                        address,
                        self.client_id
                    );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify TWS/IB Gateway is running and API connections are enabled with the correct listening port; restart it if needed.
  2. Check host/port configuration (and paper vs live port: 7497/7496, Gateway 4002/4001) and network reachability (telnet/nc the port).
  3. Increase max_attempts and the retry backoff in the connection config to tolerate slow gateway startup.
  4. Set retry_indefinitely=true if the process should keep retrying until the gateway becomes available.
  5. Catch this error at startup and re-attempt after a delay (e.g. waiting for the gateway container to become healthy).

Example fix

// before
let conn = IbConnection::new("127.0.0.1", 7497, /* max_attempts */ 3);
conn.connect_with_retry().await?;
// after
let conn = IbConnection::new("127.0.0.1", 7497, /* max_attempts */ 10);
match conn.connect_with_retry().await {
    Ok(()) => {}
    Err(e) => {
        tokio::time::sleep(Duration::from_secs(5)).await;
        conn.connect_with_retry().await?;
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-check reachability before connect_with_retry
let reachable = tokio::net::TcpStream::connect((host, port)).await.is_ok();
if !reachable {
    anyhow::bail!("IB gateway at {host}:{port} unreachable; start TWS/Gateway first");
}

Try / catch

match conn.connect_with_retry().await {
    Ok(()) => {}
    Err(e) if e.to_string().contains("Failed to connect after") => {
        tracing::error!("gateway down: {e}; retrying in 30s");
        tokio::time::sleep(Duration::from_secs(30)).await;
        conn.connect_with_retry().await?;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling connect/connect_with_retry on the IB connection when the host:port is unreachable (TWS/Gateway not running, wrong port, firewall) and max_attempts is exceeded with retry_indefinitely=false. Also produced immediately if max_attempts is configured to 0 or 1 and the first connect fails.

Common situations: TWS or IB Gateway not started or not listening on the API port (default 7497/4001); wrong host in config (localhost vs remote container); paper vs live account port mix-up; Docker networking blocking the socket; very low max_attempts with a slow-to-start gateway.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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