{"record":{"id":"ddd691a647ab6304","repo":"nikivdev/code","slug":"unhealthy-expected-http-got-2-s","errorCode":null,"errorMessage":"✗ Unhealthy: expected HTTP {}, got {} ({:.2}s)","messagePattern":"✗ Unhealthy: expected HTTP (.+?), got (.+?) \\((.+?)s\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/deploy.rs","lineNumber":3188,"sourceCode":"        .output()\n        .context(\"Failed to run curl\")?;\n\n    let elapsed = start.elapsed();\n    let status_str = String::from_utf8_lossy(&output.stdout);\n    let actual_status: u16 = status_str.trim().parse().unwrap_or(0);\n\n    if actual_status == expected_status {\n        println!(\n            \"✓ Healthy (HTTP {} in {:.2}s)\",\n            actual_status,\n            elapsed.as_secs_f64()\n        );\n        Ok(())\n    } else if actual_status == 0 {\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        bail!(\"✗ Unreachable: {}\", stderr.trim());\n    } else {\n        bail!(\n            \"✗ Unhealthy: expected HTTP {}, got {} ({:.2}s)\",\n            expected_status,\n            actual_status,\n            elapsed.as_secs_f64()\n        );\n    }\n}\n","sourceCodeStart":3170,"sourceCodeEnd":3196,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/deploy.rs#L3170-L3196","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n$ flow check --url https://app.example.com/api   # 404, route doesn't exist\n\n// after\n$ flow check --url https://app.example.com/health","handlingStrategy":"retry","validationCode":"// verify the endpoint returns the expected code first\nactual=$(curl -s -o /dev/null -w '%{http_code}' \"$URL\")\n[ \"$actual\" = \"200\" ] || echo \"warning: $URL returns $actual\"","typeGuard":null,"tryCatchPattern":"// tolerate transient 502/503 during rollout, retry N times\nmatch check_health(url, 200) {\n    Err(e) if is_transient_5xx(&e) => retry_with_backoff(3, || check_health(url, 200)),\n    other => other,\n}","preventionTips":["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"],"tags":["http","health-check","deployment","status-code"],"backgroundTag":"unexpected-http-status","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}