{"record":{"id":"fb640fb735244d71","repo":"tonhowtf/omniget","slug":"resposta-gql-sem-data","errorCode":null,"errorMessage":"Resposta GQL sem data","messagePattern":"Resposta GQL sem data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/instagram.rs","lineNumber":430,"sourceCode":"            .header(\"X-CSRFToken\", &params.csrf_token)\n            .header(\"X-FB-Friendly-Name\", \"PolarisPostActionLoadPostQueryQuery\")\n            .header(\"x-asbd-id\", \"129477\")\n            .header(\"X-Bloks-Version-Id\", &params.bloks_version_id)\n            .header(\"Referer\", \"https://www.instagram.com/\")\n            .header(\"Cookie\", &anon_cookie)\n            .body(body)\n            .send()\n            .await?;\n\n        if !response.status().is_success() {\n            return Err(anyhow!(\"Instagram GQL retornou HTTP {}\", response.status()));\n        }\n\n        let json: serde_json::Value = response.json().await?;\n\n        let data = json\n            .get(\"data\")\n            .ok_or_else(|| anyhow!(\"Resposta GQL sem data\"))?;\n\n        let media = data\n            .get(\"xdt_shortcode_media\")\n            .or_else(|| data.get(\"shortcode_media\"));\n\n        match media {\n            Some(m) if !m.is_null() => Ok(m.clone()),\n            _ => Err(anyhow!(\"Post not found via GQL\")),\n        }\n    }\n\n    async fn request_embed(&self, post_id: &str) -> anyhow::Result<serde_json::Value> {\n        let url = format!(\"https://www.instagram.com/p/{}/embed/captioned/\", post_id);\n\n        let response = self\n            .client\n            .get(&url)\n            .header(","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/instagram.rs#L412-L448","documentation":"After a successful HTTP 200 from the GraphQL endpoint, request_gql parses the JSON and requires a top-level \"data\" object. If the key is absent, the response didn't match Instagram's GQL envelope (e.g. an error JSON, challenge page, or HTML error body served with 200) and this error is thrown.","triggerScenarios":"request_gql receives HTTP 200 but json.get(\"data\") is None: Instagram returned an error object without \"data\", a bot-check/challenge response, an HTML page mislabeled as JSON, or an empty body that serde deserialized into a non-object Value.","commonSituations":"Instagram serving soft-block/challenge JSON instead of media data under 200 status; query variables invalid so GraphQL returns {\"errors\": [...]} without data; schema changes renaming the response envelope; response actually HTML (Cloudflare/anti-bot) parsed leniently.","solutions":["Log the raw response body on this error to see whether it's a GraphQL errors object, a challenge, or HTML.","Check for a top-level \"errors\" array in the JSON and surface it to diagnose bad query variables.","Retry with a fresh anonymous cookie/headers, since 200-with-challenge usually indicates bot detection.","Verify the response Content-Type is application/json before parsing; treat HTML bodies as an auth/bot failure instead."],"exampleFix":"// before\nlet data = json.get(\"data\")\n    .ok_or_else(|| anyhow!(\"Resposta GQL sem data\"))?;\n// after\nif let Some(errs) = json.get(\"errors\") {\n    anyhow::bail!(\"Instagram GQL errors: {}\", errs);\n}\nlet data = json.get(\"data\")\n    .with_context(|| format!(\"Resposta GQL sem data; body: {}\", serde_json::to_string(&json).unwrap_or_default().chars().take(500).collect::<String>()))?;","handlingStrategy":"try-catch","validationCode":"// After parsing, before trusting the shape:\nlet json: serde_json::Value = serde_json::from_str(&body)?;\nanyhow::ensure!(json.is_object(), \"GQL response is not a JSON object (got HTML/empty body?)\");\nanyhow::ensure!(json.get(\"data\").map_or(false, |d| d.is_object()), \"GQL response missing data object\");","typeGuard":"fn gql_data_field(json: &serde_json::Value) -> Option<&serde_json::Value> {\n    if json.is_object() && json.get(\"data\")?.is_object() { json.get(\"data\") } else { None }\n}","tryCatchPattern":"match platform.get_media_info(url).await {\n    Err(e) if e.to_string().contains(\"Resposta GQL sem data\") => {\n        // log raw body, refresh cookies/headers, retry once — often a soft bot-block\n        eprintln!(\"GQL envelope missing; refreshing anon cookie and retrying\");\n        refresh_anon_cookie().await?;\n        platform.get_media_info(url).await\n    }\n    other => other,\n}","preventionTips":["Always log the raw response body when the GQL envelope is missing.","Check for a top-level \"errors\" key to catch GraphQL-level failures.","Validate Content-Type is application/json before parsing.","Treat 200-but-no-data as bot detection: rotate cookies/headers and slow down."],"tags":["instagram","graphql","unexpected-response","json","rust"],"backgroundTag":"unexpected-response-shape","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"}