cube-js/cube · error · std::io::Error (ErrorKind::TimedOut, wrapped in TransportError::Connect)

connect timeout

Error message

connect timeout

What it means

Cube Store's WebSocket transport wraps the WebSocket handshake in `tokio::time::timeout(cfg.connect_timeout)`. If the TCP/TLS/WS handshake does not complete within that window, the future is cancelled and the transport raises `TransportError::Connect` carrying an `io::Error` of kind `TimedOut` with message "connect timeout". It surfaces during initial `connect` and during `attempt_reconnect` loops.

Source

Thrown at rust/cube/cubestore-ws-transport/src/actor.rs:307

        .map_err(|e| TransportError::Auth(format!("x-process-id: {e}")))?;
    builder = builder.header("x-process-id", value);

    let request = builder
        .body(())
        .map_err(|e| TransportError::InvalidUrl(e.to_string()))?;

    // Match cubestore's transport caps (default 64MiB message / 32MiB frame; the
    // server can be configured up to 256MiB). The tungstenite default of 16MiB
    // per frame is too tight for large query results.
    let ws_config = WebSocketConfig::default()
        .max_message_size(Some(256 << 20))
        .max_frame_size(Some(256 << 20));
    let connect_future = connect_async_with_config(request, Some(ws_config), false);
    let (ws, response) = tokio::time::timeout(cfg.connect_timeout, connect_future)
        .await
        .map_err(|_| {
            TransportError::Connect(tokio_tungstenite::tungstenite::Error::Io(
                std::io::Error::new(std::io::ErrorKind::TimedOut, "connect timeout"),
            ))
        })??;

    let version = response
        .headers()
        .get("X-CubeStore-Version")
        .or_else(|| response.headers().get("x-cubestore-version"))
        .and_then(|v| v.to_str().ok())
        .map(|s| s.to_string());

    Ok((ws, version))
}

fn build_ws_url(base: &url::Url) -> Result<url::Url, TransportError> {
    let mut u = base.clone();
    let path = u.path();

    // If the user already pointed at /ws (or another explicit path), keep it.

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Verify the Cube Store host/port in the connection URL and confirm the server is running (`docker ps`, `kubectl get pods`, check the listener).
  2. Test reachability from the client host: `nc -vz <host> <port>` or `curl -v http://<host>:<port>/ws`; if it hangs, fix firewall/security-group rules.
  3. Increase the configured `connect_timeout` if the network is legitimately slow (cross-region, VPN).
  4. Check reconnect/backoff settings if the error appears only during reconnection storms, and inspect Cube Store server logs for overload.

Example fix

// before: too-tight timeout against a remote cluster
cfg.connect_timeout = Duration::from_secs(2);
// after
cfg.connect_timeout = Duration::from_secs(30);
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight reachability check before opening the transport:
async fn reachable(host: &str, port: u16, timeout: Duration) -> bool {
    tokio::time::timeout(timeout, tokio::net::TcpStream::connect((host, port)))
        .await
        .map(|r| r.is_ok())
        .unwrap_or(false)
}

Type guard

fn is_connect_timeout(e: &TransportError) -> bool {
    matches!(e, TransportError::Connect(
        tokio_tungstenite::tungstenite::Error::Io(io))
        if io.kind() == std::io::ErrorKind::TimedOut)
}

Try / catch

// Match the error kind and retry with backoff:
match connect(cfg).await {
    Err(TransportError::Connect(e))
        if matches!(&e, tungstenite::Error::Io(io) if io.kind() == std::io::ErrorKind::TimedOut) =>
    {
        tokio::time::sleep(backoff.next()).await;
        retry_with_longer_timeout(cfg)
    }
    other => other,
}

Prevention

When it happens

Trigger: Connecting to a Cube Store endpoint whose host is unreachable (firewall dropping packets), wrong host/port in the connection URL, the Cube Store server process being down or overloaded, or a network with high latency exceeding `connect_timeout` (including during automatic reconnect attempts).

Common situations: Cube Store container not started or listening on a different port; Kubernetes/network-policy or cloud security group silently dropping SYNs; DNS resolving to a dead host; VPN or proxy latency; overly aggressive `connect_timeout` for a remote region.

Understand the failure class

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/89a89acc8f42da9e. Report an issue: GitHub.