tonhowtf/omniget · error · anyhow::Error

probe failed

Error message

probe failed: {}

What it means

After the HEAD phase, probe_remote sends a 1-byte ranged GET (Range: bytes=0-0) to confirm the server supports range requests. Any reqwest error from that send (DNS, TLS, reset connection, response read failure) is reported as `probe failed: {e}`. Unlike 243/244 this arm covers non-connect transport errors and errors occurring after connect.

Solutions

  1. Read the wrapped reqwest cause for the precise transport failure.
  2. Test the URL with `curl -v -r 0-0 <url>` to see the TLS/HTTP negotiation details.
  3. Retry the probe; transient resets often resolve on a second attempt.
  4. For TLS issues, add the missing root CA or disable/bypass h2 (http1_only) if the server mishandles HTTP/2.
Defensive patterns

Strategy: try-catch

Try / catch

match probe(url, headers, timeout).await {
    Err(e) if e.to_string().starts_with("probe failed:") => {
        let cause = e.to_string(); // inspect reqwest cause: tls / reset / h2
        if cause.contains("certificate") { /* fix trust store or accept CA */ }
    }
    other => { other?; }
}

Prevention

When it happens

Trigger: The GET req.send() future inside tokio::time::timeout resolves Ok(Err(e)) — e.g. TLS handshake failure, connection reset mid-request, or an HTTP/2 protocol error — for a URL that passed (or skipped) the HEAD check.

Common situations: TLS certificate problems (self-signed, expired), HTTP/2 incompatibility, servers that accept connect then drop the request, or transient network flaps between the HEAD and GET phases.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/47278cb08ce0fc13. Report an issue: GitHub.

Appendix: source

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

                content_length,
                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,

View on GitHub (pinned to 8600b91f42)