nikivdev/code · error
✗ Unhealthy: expected HTTP {}, got {} ({:.2}s)
Error message
✗ Unhealthy: expected HTTP {}, got {} ({:.2}s) What it means
The host was reachable but the HTTP status code returned by curl differs from the expected status (default 200). The error reports expected vs actual status and elapsed time so you can see what the server answered.
Source
Thrown at src/deploy.rs:3188
.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
- Inspect the returned status: if 5xx, check the server logs for a crash or bad upstream port
- If 404, verify the URL points at a route that exists (use --url with the right path)
- If the endpoint intentionally returns a different code, set the expected status for the check accordingly
- If the app was still booting, wait and rerun the health check
Example fix
// before $ flow check --url https://app.example.com/api # 404, route doesn't exist // after $ flow check --url https://app.example.com/health
Defensive patterns
Strategy: retry
Validate before calling
// verify the endpoint returns the expected code first
actual=$(curl -s -o /dev/null -w '%{http_code}' "$URL")
[ "$actual" = "200" ] || echo "warning: $URL returns $actual" Try / catch
// tolerate transient 502/503 during rollout, retry N times
match check_health(url, 200) {
Err(e) if is_transient_5xx(&e) => retry_with_backoff(3, || check_health(url, 200)),
other => other,
} Prevention
- Point the check at a stable /health endpoint, not the app root
- Delay the check until the app reports ready (or retry on 503)
- Configure the expected status to match the endpoint's contract
- Check reverse-proxy upstream ports when seeing 502
When it happens
Trigger: The deployed app answers with a non-expected status: 404 (wrong path/root route missing), 502/503 (upstream or still booting), 401/403 (auth required), or the check expects a status the endpoint never returns.
Common situations: Deployment finished but app still starting (503); reverse proxy returning 502 because the upstream port is wrong; API requires auth so root returns 401; expected_status misconfigured for an endpoint that redirects.
Related errors
- No domain configured. Use --url to specify a URL to check.
- No deployment config found. Use --url to specify a URL to ch
- device auth start failed: HTTP {}
- device auth poll failed: HTTP {}
- Maple MCP request failed ({}): {}
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/ddd691a647ab6304.
Report an issue: GitHub.