Hmbown/CodeWhale · error · anyhow::Error

Request timeout after 15 seconds

Error message

Request timeout after 15 seconds

What it means

test_api_connectivity sends a one-token, non-streaming 'hi' request through the configured provider and wraps it in tokio::time::timeout(15s). If the request neither completes nor errors within 15 seconds — it hangs — you get 'Request timeout after 15 seconds'. Real API errors (auth, HTTP 4xx/5xx, DNS failure) take the Ok(Err(e)) arm and surface their own message; only a silent hang produces this one.

Source

Thrown at crates/tui/src/lib.rs:7456

        max_tokens: 1,
        system: None,
        tools: None,
        tool_choice: None,
        metadata: None,
        thinking: None,
        // This is a one-token transport probe, not a reasoning task.
        reasoning_effort: Some("off".to_string()),
        stream: Some(false),
        temperature: None,
        top_p: None,
    };

    // Use tokio timeout to catch hanging requests
    let timeout_duration = std::time::Duration::from_secs(15);
    match tokio::time::timeout(timeout_duration, client.create_message(request)).await {
        Ok(Ok(_response)) => Ok(()),
        Ok(Err(e)) => Err(e),
        Err(_) => anyhow::bail!("Request timeout after 15 seconds"),
    }
}

fn rustc_version() -> String {
    let Some(mut cmd) = crate::dependencies::RustC::command() else {
        return "unknown".to_string();
    };
    let Ok(output) = cmd.arg("--version").output() else {
        return "unknown".to_string();
    };
    String::from_utf8(output.stdout)
        .map(|s| s.trim().to_string())
        .unwrap_or_else(|_| "unknown".to_string())
}

/// List saved sessions
fn sessions_resume_command() -> &'static str {
    "codewhale resume"

View on GitHub (pinned to 8880682c63)

Solutions

  1. Verify reachability with the same environment: curl -m 15 <api-base-url> and compare behavior
  2. Check HTTP_PROXY/HTTPS_PROXY/NO_PROXY — unset stale proxies or point them at a live proxy
  3. Adjust or disconnect the VPN so the API host is reachable
  4. Try a different network; if it works elsewhere, a local network policy is the cause
  5. Re-run the doctor/connectivity command — transient middlebox drops often clear

Example fix

# before: proxy env points at a dead local proxy
export HTTPS_PROXY=http://127.0.0.1:8888
codewhale doctor

# after
unset HTTPS_PROXY
codewhale doctor
Defensive patterns

Strategy: retry

Validate before calling

# Pre-flight: does the API base answer within 15s under the same proxy env?
curl -sS -o /dev/null -m 15 -w '%{http_code}\n' "https://<your-api-base-url>"

Try / catch

for attempt in 1..=2u32 {
    match tokio::time::timeout(std::time::Duration::from_secs(15), client.create_message(req())).await {
        Ok(Ok(_)) => return Ok(()),
        Ok(Err(e)) => return Err(e),               // real API error: do not blind-retry
        Err(_) if attempt < 2 => continue,          // hang: retry once
        Err(_) => anyhow::bail!("Request timeout after 15 seconds"),
    }
}

Prevention

When it happens

Trigger: The HTTP request stalls: a firewall silently dropping packets to the API host (connection opened or SYN never answered), HTTP_PROXY/HTTPS_PROXY pointing at a dead proxy, a VPN split-tunnel problem, or an endpoint that accepts the connection but never responds.

Common situations: Corporate proxy or VPN misconfiguration; proxy env vars left over in the shell; regional blocking of the API endpoint; DNS resolving to a black-hole address.

Understand the failure class

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/7876325f1d9326cf. Report an issue: GitHub.