xai-org/grok-build · error

Upload timed out after {}s

Error message

Upload timed out after {}s

What it means

Each upload attempt to GCS is wrapped in `tokio::time::timeout(UPLOAD_TIMEOUT, upload_bytes(...))`. If the upload does not finish within UPLOAD_TIMEOUT seconds, the timeout elapses and the future is converted into this anyhow error. The `retry` combinator then retries with backoff until retries are exhausted (which then surfaces error 406).

Source

Thrown at crates/codegen/xai-grok-pager/src/trace_cmd.rs:643

async fn upload_with_retries(
    config: &xai_grok_shell::session::repo_changes::TraceExportConfig,
    object_path: &str,
    archive: &[u8],
) -> anyhow::Result<String> {
    use backon::{ExponentialBuilder, Retryable};

    let backoff = ExponentialBuilder::default()
        .with_min_delay(std::time::Duration::from_secs(2))
        .with_max_delay(std::time::Duration::from_secs(8))
        .with_max_times(3);

    (|| async {
        tokio::time::timeout(
            UPLOAD_TIMEOUT,
            xai_file_utils::gcs::upload_bytes(config, object_path, archive, "application/gzip"),
        )
        .await
        .map_err(|_| anyhow::anyhow!("Upload timed out after {}s", UPLOAD_TIMEOUT.as_secs()))?
    })
    .retry(backoff)
    .notify(|err, dur| {
        tracing::warn!(error = %err, retry_in = ?dur, "trace_cmd: upload attempt failed, retrying");
        eprintln!("  Upload failed, retrying in {}s...", dur.as_secs());
    })
    .await
}

// ---------------------------------------------------------------------------
// Upload method resolution
// ---------------------------------------------------------------------------

pub async fn resolve_upload_method(agent_config: &AgentConfig) -> Option<UploadMethod> {
    // On login failure, fall back to ambient creds rather than erroring.
    let auth_token = xai_grok_shell::auth::ensure_authenticated_or_noninteractive(
        &agent_config.grok_com_config,
        agent_config.endpoints.has_noninteractive_upload_auth(),

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Retry `grok trace <session-id>` on a faster/more reliable connection
  2. Reduce archive size (trim session trace data) so uploads fit the timeout
  3. Check proxy/MTU/firewall issues that stall long uploads
  4. If timeouts are chronic for large traces, request a larger UPLOAD_TIMEOUT in the code/config

Example fix

// before: repeated timeouts on slow link
// after: shrink what is uploaded
let archive = build_archive(&session, /* include_payloads: */ false)?; // smaller bundle, fits timeout
Defensive patterns

Strategy: retry

Validate before calling

// estimate upload feasibility: archive size vs expected throughput within UPLOAD_TIMEOUT
let size_mb = archive.len() as f64 / 1e6;
if size_mb > 100.0 { eprintln!("archive is {size_mb}MB; may exceed upload timeout on slow links"); }

Try / catch

match upload_with_retries(...).await {
    Err(e) if e.to_string().contains("Upload timed out") => {
        eprintln!("upload exceeded timeout; check connection speed or shrink the archive, then retry");
    }
    other => other?,
}

Prevention

When it happens

Trigger: `run_upload` -> `upload_with_retries` where `gcs::upload_bytes` takes longer than UPLOAD_TIMEOUT: huge trace archives, very slow/broken network connections, or a stalled connection that never completes.

Common situations: Uploading large session bundles over slow corporate VPN; network drop mid-transfer causing a hang until timeout; proxy/firewall silently dropping long-lived connections; GCS slow under load.

Understand the failure class

Related errors


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