xai-org/grok-build · info

Connection cancelled

Error message

Connection cancelled

What it means

connect_to_relay races the WebSocket connection attempt against a cancellation token via tokio::select!. If the cancellation token fires before the connection completes, the function bails with "Connection cancelled" instead of continuing to connect.

Source

Thrown at crates/codegen/xai-grok-shell/src/agent/relay.rs:415

    );
    Ok(req)
}
/// Attempt to connect to the relay WebSocket server.
///
/// If `proxy_url` is `Some`, the connection is established through an HTTP
/// CONNECT tunnel.  Otherwise, a direct connection is used.
async fn connect_to_relay(
    config: &RelayConfig,
    proxy_url: Option<&str>,
    cancel: &CancellationToken,
) -> anyhow::Result<
    tokio_tungstenite::WebSocketStream<tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>>,
> {
    let req = build_relay_request(config)?;
    let connect_timeout = Duration::from_secs(CONNECT_TIMEOUT_SECS);
    tokio::select! {
        _ = cancel.cancelled() => {
            anyhow::bail!("Connection cancelled");
        }
        result = tokio::time::timeout(connect_timeout, async {
            if let Some(proxy_url) = proxy_url {
                // Proxy path: open TCP to proxy, send CONNECT, then WS handshake.
                let target_host = req.uri().host()
                    .ok_or_else(|| anyhow::anyhow!("WebSocket URL has no host"))?;
                let target_port = req.uri().port_u16().unwrap_or(443);
                let tunneled_stream = proxy::connect_via_proxy(
                    proxy_url,
                    target_host,
                    target_port,
                ).await?;
                // Perform the WebSocket handshake over the tunneled stream.
                let (ws, resp) = tokio_tungstenite::client_async(req, tunneled_stream)
                    .await
                    .map_err(|e| anyhow::Error::from(e).context("WebSocket handshake via proxy failed"))?;
                Ok((ws, resp))
            } else {

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Treat this as an expected cooperative-cancel signal — check whether shutdown/reconnect was intended.
  2. If it fires unexpectedly, audit what triggers the cancellation token (e.g. run_relay_loop restart logic).
  3. Retry the connection if cancellation was spurious and the session should persist.

Example fix

// before
let ws = connect_to_relay(&config, &cancel, proxy_url).await?;
// after
match connect_to_relay(&config, &cancel, proxy_url).await {
    Ok(ws) => ws,
    Err(e) if e.to_string() == "Connection cancelled" => return Ok(()), // graceful shutdown
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: try-catch

Try / catch

match connect_to_relay(&config, &cancel, proxy).await {
    Err(e) if e.to_string() == "Connection cancelled" => {
        // expected during shutdown/reconnect — exit cleanly, don't log as error
        return Ok(());
    }
    Err(e) => return Err(e),
    Ok(ws) => use_ws(ws),
}

Prevention

When it happens

Trigger: The cancel token (passed into connect_to_relay from run_relay_loop) is cancelled during the CONNECT_TIMEOUT_SECS-bounded connection attempt — typically shutdown, reconnect-with-new-session, or user abort racing the handshake.

Common situations: User interrupts the agent while it is dialing the relay; the relay loop initiates a reconnect and cancels the in-flight old connection; application shutdown during slow network startup.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/a4598ce7af6b0b10. Report an issue: GitHub.