{"record":{"id":"74351eef0ff03638","repo":"tonhowtf/omniget","slug":"bluesky-api-retornou-http-mod","errorCode":null,"errorMessage":"Bluesky API retornou HTTP {}","messagePattern":"Bluesky API retornou HTTP (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/platforms/bluesky/mod.rs","lineNumber":139,"sourceCode":"        let segments: Vec<&str> = parsed.path().split('/').filter(|s| !s.is_empty()).collect();\n        if segments.len() >= 4 && segments[0] == \"profile\" && segments[2] == \"post\" {\n            return Some((segments[1].to_string(), segments[3].to_string()));\n        }\n        None\n    }\n\n    async fn fetch_post(&self, user: &str, post_id: &str) -> anyhow::Result<serde_json::Value> {\n        let uri = format!(\"at://{}/app.bsky.feed.post/{}\", user, post_id);\n        let url = format!(\n            \"{}?depth=0&parentHeight=0&uri={}\",\n            API_BASE,\n            urlencoding::encode(&uri)\n        );\n\n        let response = self.client.get(&url).send().await?;\n\n        if !response.status().is_success() {\n            return Err(anyhow!(\"Bluesky API retornou HTTP {}\", response.status()));\n        }\n\n        let json: serde_json::Value = response.json().await?;\n\n        if let Some(error) = json.get(\"error\").and_then(|e| e.as_str()) {\n            return match error {\n                \"NotFound\" | \"InternalServerError\" => Err(anyhow!(\"Post not available\")),\n                \"InvalidRequest\" => Err(anyhow!(\"Unsupported link\")),\n                _ => Err(anyhow!(\"Erro da API: {}\", error)),\n            };\n        }\n\n        Ok(json)\n    }\n}\n\nenum BlueskyMedia {\n    Video { hls_url: String },","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/platforms/bluesky/mod.rs#L121-L157","documentation":"In `fetch_post` (src-tauri/src/platforms/bluesky/mod.rs:139), the request to the Bluesky AppView (`app.bsky.feed.getPostThread`) returned a non-2xx HTTP status, and the code converts it into the error \"Bluesky API retornou HTTP {status}\". This fires before the response body is parsed, so the failure is at the HTTP transport/status level.","triggerScenarios":"The GET to the AppView endpoint returns statuses like 400 (malformed uri), 403, 429 (rate limit), or 5xx; any `!response.status().is_success()` triggers this branch.","commonSituations":"Bluesky rate limiting during heavy use; AppView outages (5xx); an incorrectly constructed at:// URI producing a 400; transient network/proxy failures surfaced as error statuses.","solutions":["Check the status code in the message: 429 means back off and retry later; 5xx means wait for Bluesky recovery.","Verify the constructed at:// URI and handle are valid before the request.","Add retry with exponential backoff for 429/5xx responses.","Inspect the response body (currently discarded) for the AppView's structured error message."],"exampleFix":"// before\nif !response.status().is_success() {\n    return Err(anyhow!(\"Bluesky API retornou HTTP {}\", response.status()));\n}\n// after\nif !response.status().is_success() {\n    let status = response.status();\n    let body = response.text().await.unwrap_or_default();\n    anyhow::bail!(\"Bluesky API retornou HTTP {}: {}\", status, body);\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in 0..3 {\n    match self.fetch_post(&user, &post_id).await {\n        Ok(json) => return Ok(json),\n        Err(e) if e.to_string().contains(\"HTTP 429\") || e.to_string().contains(\"HTTP 5\") => {\n            tokio::time::sleep(std::time::Duration::from_secs(2 << attempt)).await;\n        }\n        Err(e) => return Err(e),\n    }\n}","preventionTips":["Throttle request rate to avoid AppView 429s.","Include the response body in the error for diagnosis.","Monitor Bluesky status before debugging your own code on 5xx."],"tags":["rust","bluesky","http","api"],"backgroundTag":"http-error-response","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}