xai-org/grok-build · error
GCS download failed: {}
Error message
GCS download failed: {} What it means
download_file fetches a session artifact from a signed GCS URL via the raw HTTP client. After sending the GET, any non-2xx status is converted into this error carrying the HTTP status code. It signals that the signed URL was rejected or the object is not retrievable, not a local I/O problem.
Source
Thrown at crates/codegen/xai-grok-shell/src/agent/session_registry_client.rs:368
let url = format!("{}/sessions/{}/download", self.base_url, session_id);
let builder = self
.get(&url)
.query(&[("file", file), ("turn", &turn.to_string())]);
let (response, stamp) = self.send_authed(builder, "session download").await?;
if !response.status().is_success() {
return Err(self.check_response(response, stamp.as_ref(), "session download"));
}
let resp: DownloadResponse = response.json().await.context("parse download response")?;
// Stream from the signed GCS URL directly to disk (archives can be hundreds of MB)
let mut gcs_response = self
.raw_client
.get(&resp.download_url)
.send()
.await
.context("download from GCS")?;
if !gcs_response.status().is_success() {
anyhow::bail!("GCS download failed: {}", gcs_response.status());
}
if let Some(parent) = dest.parent() {
tokio::fs::create_dir_all(parent).await?;
}
let mut out = tokio::fs::File::create(dest)
.await
.context("create dest file")?;
let chunk_timeout = std::time::Duration::from_secs(60);
loop {
match tokio::time::timeout(chunk_timeout, gcs_response.chunk()).await {
Ok(Ok(Some(chunk))) => {
tokio::io::AsyncWriteExt::write_all(&mut out, &chunk)
.await
.context("write chunk to disk")?;
}
Ok(Ok(None)) => break,
Ok(Err(e)) => return Err(e).context("read GCS chunk"),
Err(_) => anyhow::bail!(View on GitHub (pinned to bc7f02eddd)
Solutions
- Re-fetch a fresh download URL from the session registry and retry the download immediately
- Verify the object still exists in the GCS bucket (gsutil ls / console) for the session id
- Check network/proxy configuration so storage.googleapis.com is reachable
- Retry on 5xx with backoff; treat 403/404 as fatal and obtain a new session or artifact
Example fix
// before
let resp = client.raw_client.get(&stale_url).send().await?;
// after: obtain a fresh URL then retry once on failure
let resp = client.raw_client.get(&fresh_url).send().await?;
if !resp.status().is_success() {
let fresh = registry.get_download_url(&session_id).await?;
resp = client.raw_client.get(&fresh).send().await?;
} Defensive patterns
Strategy: retry
Validate before calling
// Optionally pre-check reachability
let head = client.raw_client.head(&download_url).send().await?;
if !head.status().is_success() {
eprintln!("download URL unusable ({}); refresh it", head.status());
} Try / catch
match download_file(&client, &url, &dest).await {
Ok(()) => {},
Err(e) if e.to_string().contains("GCS download failed") => {
let fresh = registry.get_download_url(&session_id).await?;
download_file(&client, &fresh, &dest).await?;
},
Err(e) => return Err(e),
} Prevention
- Download immediately after obtaining the signed URL — they expire
- Wrap downloads in one bounded retry with fresh URL re-fetch
- Monitor object retention policies so artifacts outlive expected download windows
When it happens
Trigger: Calling download_file (e.g. via the session registry client) when the GCS GET returns a non-success status such as 403 (expired/revoked signed URL), 404 (object deleted), or 5xx from Google Cloud Storage.
Common situations: Signed download URLs expiring before use, artifacts garbage-collected after a session is reaped, proxy/firewall blocking storage.googleapis.com, or GCS transient outages returning 500/503.
Related errors
- Download failed: HTTP {}
- response missing Content-Length
- no artifact at {base}/{object_name}
- GCS channel pointer fetch failed for {}: {:#}
- GCS channel pointer fetch failed: HTTP {} for {}: {}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/1aff7517e0b2893e.
Report an issue: GitHub.