nautechsystems/nautilus_trader · error · anyhow::Error

Gateway `{}` not ready after {} seconds

Error message

Gateway `{}` not ready after {} seconds

What it means

DockerizedIBGateway::start polls the container once per second (for up to the configured timeout or an explicit wait value) checking whether the gateway reports logged-in status. If the gateway never becomes ready within that window, start bails with the container name and elapsed seconds.

Source

Thrown at crates/adapters/interactive_brokers/src/gateway/dockerized.rs:460

        let wait_time = wait.unwrap_or(self.config.timeout);
        let mut waited = 0u64;

        while waited < wait_time {
            if self.is_logged_in(&container_id).await.unwrap_or(false) {
                tracing::debug!(
                    "Gateway `{}` ready. VNC port is {:?}",
                    self.container_name,
                    self.config.vnc_port
                );
                return Ok(());
            }

            tracing::debug!("Waiting for IB Gateway to start");
            tokio::time::sleep(Duration::from_secs(1)).await;
            waited += 1;
        }

        anyhow::bail!(
            "Gateway `{}` not ready after {} seconds",
            self.container_name,
            wait_time
        )
    }

    /// Safely start the gateway, handling container already exists errors.
    ///
    /// # Arguments
    ///
    /// * `wait` - Optional wait time in seconds
    ///
    /// # Errors
    ///
    /// Returns an error if startup fails (other than container exists).
    pub async fn safe_start(&mut self, wait: Option<u64>) -> anyhow::Result<()> {
        match self.start(wait).await {
            Ok(()) => Ok(()),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Confirm the 2FA/I.login prompt was accepted in the IB Gateway UI or mobile app (check via the container's VNC port) Increase DockerizedIBGatewayConfig.timeout (or pass a larger wait to start) and retry Check container logs: docker logs <container_name> for credential/config errors Verify the gateway image and paper/live trading mode match your credentials

Example fix

// before
let config = DockerizedIBGatewayConfig { timeout: 60, .. };
// after
let config = DockerizedIBGatewayConfig { timeout: 300, .. }; // allow time for 2FA
Defensive patterns

Strategy: retry

Validate before calling

// before starting, ensure Docker is up and image is present
// docker info && docker image inspect <gateway_image>

Try / catch

loop {
    match gateway.start(Some(300)).await {
        Ok(()) => break,
        Err(e) if e.to_string().contains("not ready after") => {
            warn!("gateway not ready: {e}; retrying with longer timeout");
            tokio::time::sleep(Duration::from_secs(10)).await;
        }
        Err(e) => return Err(e),
    }
}

Prevention

When it happens

Trigger: start() -> is_logged_in() keeps returning false until waited >= wait_time (config timeout or the wait argument). Commonly because IB credentials/2FA were not approved, the gateway image is slow to pull/start, or the container is crash-looping.

Common situations: First-time 2FA notification not confirmed in IB's mobile app; wrong trading mode (paper vs live) credentials; slow machine or cold Docker daemon exceeding the default timeout; gateway container restarting due to bad config.

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/3bbfe132407a953e. Report an issue: GitHub.