{"record":{"id":"4b01cfd7e3f6aec0","repo":"tonhowtf/omniget","slug":"x-resposta-invalida","errorCode":null,"errorMessage":"X {}: resposta invalida ({})","messagePattern":"X (.+?): resposta invalida \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/x/client.rs","lineNumber":322,"sourceCode":"            return Err(anyhow!(\"X_RATE_LIMIT:{}\", reset));\n        }\n        let text = resp.text().await.unwrap_or_default();\n        if status.as_u16() == 404 {\n            return Ok(Err(\"not_found\".into()));\n        }\n        if status.as_u16() == 401 || status.as_u16() == 403 {\n            return Ok(Err(format!(\"auth:{}\", status.as_u16())));\n        }\n        if !status.is_success() {\n            return Err(anyhow!(\n                \"X {}: HTTP {} {}\",\n                op,\n                status,\n                text.chars().take(200).collect::<String>()\n            ));\n        }\n        let v: Value = serde_json::from_str(&text)\n            .map_err(|e| anyhow!(\"X {}: resposta invalida ({})\", op, e))?;\n        if v.get(\"data\")\n            .map(|d| d.is_null() || d.as_object().map(|o| o.is_empty()).unwrap_or(false))\n            .unwrap_or(true)\n        {\n            if let Some(msg) = v\n                .get(\"errors\")\n                .and_then(|e| e.as_array())\n                .and_then(|a| a.first())\n                .and_then(|e| e.get(\"message\"))\n                .and_then(|m| m.as_str())\n            {\n                if msg.contains(\"Query not found\") || msg.contains(\"query_id\") {\n                    return Ok(Err(\"not_found\".into()));\n                }\n                return Err(anyhow!(\"X {}: {}\", op, msg));\n            }\n        }\n        Ok(Ok(v))","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/x/client.rs#L304-L340","documentation":"After a successful HTTP status, check() parses the body as JSON; a serde failure raises 'X <op>: resposta invalida (<serde error>)', meaning X returned 2xx but the body is not valid JSON. It then also guards against a null/empty 'data' field as a separate no-data path.","triggerScenarios":"check() getting a 2xx response whose body fails serde_json::from_str — HTML error/challenge pages, empty bodies, or BOM/compressed content mis-decoded as text.","commonSituations":"X serving an anti-bot challenge page with HTTP 200; captive portal or proxy injecting HTML; content-encoding mismatch causing garbled text.","solutions":["Inspect the raw body — if it is HTML, X is challenging/blocking the client; slow down or authenticate.","Log the first bytes of the response and the serde error to identify corruption or encoding issues.","Ensure the request sets Accept: application/json and does not disable/miss decompression.","Retry after backoff; challenge pages are often transient for flagged IPs."],"exampleFix":"// before\nlet v: Value = serde_json::from_str(&text).map_err(|e| anyhow!(\"X {}: resposta invalida ({})\", op, e))?;\n// after\nlet v: Value = serde_json::from_str(&text).map_err(|e| {\n    tracing::warn!(op, snippet = %text.chars().take(120).collect::<String>(), \"non-JSON 2xx from X\");\n    anyhow!(\"X {}: resposta invalida ({})\", op, e)\n})?;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_json(text: &str) -> bool {\n    serde_json::from_str::<serde_json::Value>(text).is_ok()\n}","tryCatchPattern":"match gql(op).await {\n    Err(e) if e.to_string().contains(\"resposta invalida\") => {\n        // body was not JSON: likely a challenge page\n        slow_down_and_authenticate();\n        Err(e)\n    }\n    other => other,\n}","preventionTips":["Send Accept: application/json and correct Accept-Encoding headers.","Treat HTML-in-2xx as an anti-bot signal and reduce request rate.","Log a body snippet with the parse error to distinguish challenge vs corruption.","Prefer authenticated sessions, which receive fewer challenge pages."],"tags":["x-api","json","response-parsing","anti-bot"],"backgroundTag":"invalid-json-response","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}