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
- Treat this as an expected cooperative-cancel signal — check whether shutdown/reconnect was intended.
- If it fires unexpectedly, audit what triggers the cancellation token (e.g. run_relay_loop restart logic).
- 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
- Treat this message as a cooperative-cancel signal, not a failure
- Avoid cancelling the token spuriously during startup; only cancel on real shutdown/reconnect
- Pattern-match the exact message when distinguishing cancel from real connection errors
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
- Authentication cancelled
- cancelled during ignored-only copy
- cancelled after git worktree add
- cancelled after parallel copy
- WebSocket connection timed out after {} seconds
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/a4598ce7af6b0b10.
Report an issue: GitHub.