nikivdev/code · error

✗ Unreachable: {}

Error message

✗ Unreachable: {}

What it means

The health check shells out to curl; a parsed status of 0 means curl exited nonzero without producing an HTTP status, i.e. the host could not be reached at all. The trimmed curl stderr (DNS failure, TLS error, connection refused) is included in the message.

Source

Thrown at src/deploy.rs:3186

            &url,
        ])
        .output()
        .context("Failed to run curl")?;

    let elapsed = start.elapsed();
    let status_str = String::from_utf8_lossy(&output.stdout);
    let actual_status: u16 = status_str.trim().parse().unwrap_or(0);

    if actual_status == expected_status {
        println!(
            "✓ Healthy (HTTP {} in {:.2}s)",
            actual_status,
            elapsed.as_secs_f64()
        );
        Ok(())
    } else if actual_status == 0 {
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!("✗ Unreachable: {}", stderr.trim());
    } else {
        bail!(
            "✗ Unhealthy: expected HTTP {}, got {} ({:.2}s)",
            expected_status,
            actual_status,
            elapsed.as_secs_f64()
        );
    }
}

View on GitHub (pinned to a747e741ae)

Solutions

  1. Read the curl stderr in the message and fix the underlying cause (DNS, refused connection, TLS)
  2. Verify the service is actually running and listening on the expected host/port
  3. Re-check after DNS propagation or with the correct URL via --url
  4. Ensure curl is installed and proxy env vars (HTTP(S)_PROXY) are set correctly

Example fix

// before
url = "http://localhost:9999"   # nothing listening

// after
url = "http://localhost:8080"   # app actually bound here
Defensive patterns

Strategy: retry

Validate before calling

// pre-check reachability before the managed health check
curl -sSf --max-time 5 "$URL" -o /dev/null || echo "host unreachable: $URL"

Try / catch

// retry with backoff for boot-time unreachability
for attempt in 1..=5 {
    match check_health(url).await {
        Ok(()) => break,
        Err(e) if e.to_string().contains("Unreachable") && attempt < 5 => {
            tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await;
        }
        Err(e) => return Err(e),
    }
}

Prevention

When it happens

Trigger: curl fails to connect: DNS does not resolve, connection refused/timeout, TLS handshake failure, or curl is missing/unusable so the command errors before any HTTP response.

Common situations: Checking a domain before DNS propagates; app not yet started or crashed; wrong port in URL; corporate proxy/firewall blocking outbound requests; running offline.

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


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/2e0a0f5b2353a2e7. Report an issue: GitHub.