{"record":{"id":"40c90d3db2f0a3f3","repo":"tonhowtf/omniget","slug":"graph-api","errorCode":null,"errorMessage":"Graph API: {}","messagePattern":"Graph API: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/instagram/publish.rs","lineNumber":549,"sourceCode":"// ── API oficial (Graph) ──────────────────────────────────────────────────\n\n#[derive(Debug, Clone, Serialize, Deserialize, Default)]\npub struct GraphAuth {\n    pub access_token: String,\n    pub ig_user_id: String,\n}\n\nconst GRAPH: &str = \"https://graph.facebook.com/v21.0\";\n\nasync fn graph_post(\n    http: &reqwest::Client,\n    url: &str,\n    form: &[(&str, String)],\n) -> anyhow::Result<Value> {\n    let resp = http.post(url).form(form).send().await?;\n    let json: Value = resp.json().await?;\n    if let Some(err) = json.get(\"error\") {\n        return Err(anyhow!(\n            \"Graph API: {}\",\n            err.get(\"message\")\n                .and_then(|m| m.as_str())\n                .unwrap_or(\"erro\")\n        ));\n    }\n    Ok(json)\n}\n\nasync fn graph_get(http: &reqwest::Client, url: &str) -> anyhow::Result<Value> {\n    let json: Value = http.get(url).send().await?.json().await?;\n    if let Some(err) = json.get(\"error\") {\n        return Err(anyhow!(\n            \"Graph API: {}\",\n            err.get(\"message\")\n                .and_then(|m| m.as_str())\n                .unwrap_or(\"erro\")\n        ));","sourceCodeStart":531,"sourceCodeEnd":567,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/instagram/publish.rs#L531-L567","documentation":"graph_post is the low-level POST helper for the Instagram Graph API. After sending the form it parses the JSON response; if the payload contains an \"error\" object, it raises \"Graph API: <message>\" using the message field (or the literal \"erro\" when absent). This is the relay of Facebook/Instagram's structured API error into the library's anyhow error type.","triggerScenarios":"Any POST made by graph_post (called from publish_graph, e.g. POST {GRAPH}/{user}/media or /media_publish) where Instagram returns 200 with an \"error\" JSON object — expired/invalid access token, missing permissions (instagram_content_publish), unsupported media URL, rate limiting.","commonSituations":"Long-lived token expired or revoked; app not in production/live mode so publishing is blocked; page connected account misconfigured; media URL not publicly reachable so Instagram rejects it.","solutions":["Read the message after \"Graph API: \" and follow the Graph API error-code docs (e.g. code 190 = token problem, code 10 = permission)","Refresh/regenerate the access token and confirm the instagram_content_publish permission is granted","Verify the media URLs are publicly accessible over HTTPS and the IG account is a Business/Creator account linked to a Facebook Page"],"exampleFix":"// before\nlet resp = graph_post(&http, &url, &[(\"access_token\", token)]).await?;\n// after (inspect error details first)\nmatch graph_post(&http, &url, &form).await {\n    Err(e) if e.to_string().starts_with(\"Graph API: 190\") => refresh_token_and_retry(),\n    r => r,\n}","handlingStrategy":"try-catch","validationCode":"// preflight: verify token before publishing\nlet ok = http.get(format!(\"{GRAPH}/{ig_user}?fields=id&access_token={token}\"))\n    .send().await?.json::<Value>().await?\n    .get(\"error\").is_none();\nif !ok { return Err(\"token/credenciais inválidas antes de publicar\"); }","typeGuard":null,"tryCatchPattern":"match publish_graph(&auth, &req).await {\n    Err(e) if e.to_string().contains(\"Graph API: 190\") => refresh_token_and_retry().await,\n    Err(e) => Err(e),\n    Ok(r) => Ok(r),\n}","preventionTips":["Refresh long-lived tokens before they expire and store expiry timestamps","Request the instagram_content_publish permission during OAuth","Pre-check media URLs are publicly reachable (HEAD 200) before publishing"],"tags":["instagram","graph-api","api-error"],"backgroundTag":"api-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"}