tonhowtf/omniget · error · anyhow::Error
unreachable
Error message
unreachable: {} What it means
probe_remote first issues a HEAD request to decide whether a cheap 1-byte GET probe is needed. When the HEAD fails with a reqwest connect error (e.is_connect()), the host is definitively unreachable, so the function fails fast instead of paying a second full timeout on the GET probe. The underlying connect error is interpolated into the message.
Solutions
- Read the interpolated cause (DNS vs refused vs tls) to identify the exact connect failure.
- Verify the URL's host and port are correct and the server is listening (curl -I <url>).
- Check DNS resolution and firewall/proxy rules for the target host.
- If behind a proxy, ensure reqwest's proxy configuration matches the environment.
Defensive patterns
Strategy: retry
Validate before calling
// caller-side reachability pre-check
let host = url.host_str().ok_or("missing host")?;
let port = url.port_or_known_default().unwrap_or(80);
std::net::TcpStream::connect((host, port)).is_ok() Try / catch
match probe(url).await {
Err(e) if e.to_string().starts_with("unreachable:") => {
// host down: surface a user-facing 'server unreachable' state, schedule retry with backoff
}
other => { other?; }
} Prevention
- Validate URL host/port before probing; typos in port are the top cause.
- Implement exponential backoff retries for probe calls.
- Check DNS and firewall rules in the deployment environment.
- Configure proxy settings explicitly when running behind corporate proxies.
When it happens
Trigger: Calling probe/probe_url for a URL whose host refuses TCP connections (port closed), fails DNS, or otherwise errors at the connect layer, and the HEAD attempt returns Ok(Err(e)) with e.is_connect() true.
Common situations: Wrong port in the URL, server down or firewall dropping traffic, DNS name no longer resolving, or testing against localhost when the service is not running.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- unreachable: connect timed out after
- probe failed
- probe timed out
- probe returned HTTP
- YouTube não retornou URL
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/ec49c505cf26007b.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/http_fetcher.rs:677
url: &str,
headers: Option<&reqwest::header::HeaderMap>,
timeout: Duration,
) -> anyhow::Result<RemoteProbe> {
let mut req = client.head(url);
if let Some(h) = headers {
req = req.headers(h.clone());
}
let head = match tokio::time::timeout(timeout, req.send()).await {
Ok(Ok(r)) if r.status().is_success() => Some(r),
Ok(Ok(r)) => {
tracing::debug!("[http_fetcher] HEAD returned HTTP {}", r.status());
None
}
// Sem conexão não adianta tentar o GET de 1 byte: é o mesmo host.
// Falhar aqui poupa um segundo timeout inteiro por tentativa quando o
// servidor está fora (proof.ovh.net levou 495 s para desistir).
Ok(Err(e)) if e.is_connect() => {
return Err(anyhow!("unreachable: {}", e));
}
Ok(Err(e)) => {
tracing::debug!("[http_fetcher] HEAD failed: {}", e);
None
}
Err(_) => {
return Err(anyhow!(
"unreachable: connect timed out after {:?}",
timeout
));
}
};
if let Some(resp) = head {
let h = resp.headers();
let content_length = header_content_length(h);
let accept_ranges = h
.get(reqwest::header::ACCEPT_RANGES)View on GitHub (pinned to 8600b91f42)