Hmbown/CodeWhale · error · anyhow::Error

Request timeout after 15 seconds

Error message

Request timeout after 15 seconds

What it means

A connectivity self-test wraps client.create_message in a 15-second tokio timeout. If no response (success or provider error) arrives in time, the probe aborts with this message. It distinguishes a hanging/stalled request from an actual API error returned within the window.

Solutions

  1. Retry — transient provider slowness may resolve
  2. Check the provider base URL / proxy configuration for a silently hanging endpoint
  3. Test the endpoint with curl to confirm it responds within 15s
  4. Check network/firewall/VPN conditions that drop traffic
Defensive patterns

Strategy: retry

Validate before calling

if !endpoint_reachable(base_url, std::time::Duration::from_secs(5)) { warn!("endpoint not reachable before request"); }

Try / catch

match result { Err(e) if e.to_string().contains("Request timeout") => { /* retry with backoff or surface connectivity guidance */ }, other => other? }

Prevention

When it happens

Trigger: Calling the TUI's connectivity check when the provider endpoint accepts the create_message request but never responds within 15 seconds — e.g. a proxy that swallows the request, a DNS resolve that hangs, or a slow model that streams nothing before the deadline.

Common situations: Corporate proxy or VPN stalling requests; wrong base URL pointing at a silent endpoint; overloaded provider taking >15s to answer a simple message; firewall dropping packets silently.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/7876325f1d9326cf. Report an issue: GitHub.

Appendix: source

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

        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 {
    // `RustC::available()` resolves the tool once, capturing the `--version`
    // banner as a side effect of the probe; reuse it instead of launching a
    // second rustc process (each launch loads libLLVM).
    if !crate::dependencies::RustC::available() {
        return "unknown".to_string();
    }
    crate::dependencies::rustc_version_banner().unwrap_or_else(|| "unknown".to_string())
}

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

View on GitHub (pinned to 73e0f67d83)