tonhowtf/omniget · error · anyhow::Error

probe timed out

Error message

probe timed out

What it means

The 1-byte ranged GET in probe_remote is bounded by tokio::time::timeout. If req.send() does not produce a response within the configured duration, the Err(_) arm returns this static message. It means the server connected (or HEAD succeeded) but never delivered the GET response in time.

Solutions

  1. Increase the timeout parameter passed to probe_remote.
  2. Re-run the probe to rule out a one-off stall.
  3. Check server-side load or rate limiting (headers like Retry-After, 429s on other endpoints).
  4. Reduce probe frequency or add backoff if probing many URLs against the same host.
Defensive patterns

Strategy: retry

Try / catch

match probe(url, headers, timeout).await {
    Err(e) if e.to_string() == "probe timed out" => {
        // retry with 2x timeout, then mark host slow/unavailable
    }
    other => { other?; }
}

Prevention

When it happens

Trigger: Calling probe/probe_url against a server that accepts the connection but stalls before answering the bytes=0-0 GET, exceeding the probe timeout.

Common situations: Extremely slow origin servers, rate-limited or tarpitting hosts, mobile/satellite links with long RTTs, or a timeout value configured too tightly for the environment.

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 tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/c82b9146a1ded86d. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/http_fetcher.rs:720

                accept_ranges,
                content_type: h
                    .get(reqwest::header::CONTENT_TYPE)
                    .and_then(|v| v.to_str().ok())
                    .map(|s| s.to_string()),
                filename: header_filename(h),
                method: "HEAD",
            });
        }
    }

    let mut req = client.get(url).header(reqwest::header::RANGE, "bytes=0-0");
    if let Some(h) = headers {
        req = req.headers(headers_without_range(h));
    }
    let resp = match tokio::time::timeout(timeout, req.send()).await {
        Ok(Ok(r)) => r,
        Ok(Err(e)) => return Err(anyhow!("probe failed: {}", e)),
        Err(_) => return Err(anyhow!("probe timed out")),
    };
    let status = resp.status();
    if !status.is_success() {
        return Err(anyhow!("probe returned HTTP {}", status));
    }
    let h = resp.headers().clone();
    let content_type = h
        .get(reqwest::header::CONTENT_TYPE)
        .and_then(|v| v.to_str().ok())
        .map(|s| s.to_string());
    let filename = header_filename(&h);
    let probe = if status == reqwest::StatusCode::PARTIAL_CONTENT {
        RemoteProbe {
            content_length: content_range_total(&h),
            accept_ranges: true,
            content_type,
            filename,
            method: "GET range",

View on GitHub (pinned to 8600b91f42)