{"record":{"id":"88a231e2b5657790","repo":"nikivdev/code","slug":"api-error","errorCode":null,"errorMessage":"API error {}: {}","messagePattern":"API error (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/env.rs","lineNumber":1456,"sourceCode":"    let resp = client\n        .post(url)\n        .header(\"Authorization\", format!(\"Bearer {}\", token))\n        .json(&body)\n        .send()\n        .context(\"failed to connect to cloud\")?;\n\n    if resp.status() == 404 {\n        return Ok(identity);\n    }\n\n    if resp.status() == 401 {\n        bail!(\"Unauthorized. Check your token with `f env login`.\");\n    }\n\n    if !resp.status().is_success() {\n        let status = resp.status();\n        let body = resp.text().unwrap_or_default();\n        bail!(\"API error {}: {}\", status, body);\n    }\n\n    Ok(identity)\n}\n\nfn fetch_project_member_sealer_ids(\n    project_name: &str,\n    self_sealer_id: &str,\n    api_url: &str,\n    token: &str,\n    client: &reqwest::blocking::Client,\n) -> Result<Vec<String>> {\n    let url = Url::parse(&format!(\n        \"{}/api/env/projects/{}/sealers\",\n        api_url, project_name\n    ))?;\n    let resp = client\n        .get(url)","sourceCodeStart":1438,"sourceCodeEnd":1474,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/env.rs#L1438-L1474","documentation":"This error is raised by `fetch_project_sealed_env` (and sibling cloud fetches) in src/env.rs when the remote API responds with any non-2xx, non-401, non-404 status. The library embeds the HTTP status code and the raw response body into the message so the developer can see exactly what the server rejected and why.","triggerScenarios":"A `reqwest` GET/POST to the cloud env endpoint returns a status that is not 2xx, not 401, and not 404 — e.g. 403 Forbidden (token valid but lacking project access), 429 Too Many Requests, or 500/502/503 from the server.","commonSituations":"Expired-but-not-revoked token hitting a project the account is no longer a member of (403); server-side outage or rate limiting (429/5xx); API version mismatch after a server upgrade returning 400 Bad Request; proxy or corporate firewall altering requests.","solutions":["Read the status and body in the message: 5xx/429 usually mean retry later with backoff; 403 means fix project membership/permissions","Run `f env login` to obtain a fresh token, then retry","Check the response body for a server-side error message pointing at the failing request field","Verify network/proxy settings if the body looks like an HTML error page from an intermediary"],"exampleFix":"// before: no handling of 429/5xx\nlet identity = fetch_sealed_env(...)?;\n// after: retry transient statuses\nmatch fetch_sealed_env(...) {\n    Err(e) if is_retryable(&e) => retry_with_backoff(3, || fetch_sealed_env(...)),\n    other => other,\n}","handlingStrategy":"retry","validationCode":"// Rust: cheap preflight to catch auth/permission issues before heavy work\npub fn preflight(client: &Client, token: &str) -> Result<(), Error> {\n    let r = client.get(\"/api/me\").bearer_auth(token).send()?;\n    match r.status() {\n        s if s.is_success() => Ok(()),\n        s => Err(Error::msg(format!(\"preflight failed: {}\", s))),\n    }\n}","typeGuard":"pub fn is_api_error(e: &Error) -> bool {\n    e.to_string().starts_with(\"API error \")\n}\npub fn api_status(e: &Error) -> Option<u16> {\n    e.to_string().splitn(3, ' ').nth(2)?.split(':').next()?.parse().ok()\n}","tryCatchPattern":"match api_status(&err) {\n    Some(429) | Some(500..=599) => retry_with_backoff(3, op),\n    Some(403) => eprintln!(\"permission denied: request project access\"),\n    _ => return Err(err),\n}","preventionTips":["Preflight the token with a cheap authenticated call before large operations","Only retry 429/5xx; never retry 403/401 blindly","Check project membership/role before operations requiring permissions","Respect Retry-After headers on 429 responses"],"tags":["http","api","network","rust"],"backgroundTag":"http-api-error-response","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}