{"record":{"id":"3d6edb0e8b8a77ad","repo":"tonhowtf/omniget","slug":"a-resposta-da-api-do-tiktok-n-o-era-json","errorCode":null,"errorMessage":"a resposta da API do TikTok não era JSON","messagePattern":"a resposta da API do TikTok não era JSON","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/tiktok/favorites.rs","lineNumber":399,"sourceCode":"        opts.limit\n    };\n    for _ in 0..200 {\n        let url = item_list_url(&opts.source, &sec_uid, &cursor, 30)\n            .ok_or_else(|| anyhow!(\"fonte desconhecida: {}\", opts.source))?;\n        pacer.wait().await;\n        let resp = client.get(&url).header(\"Referer\", &profile).send().await?;\n        if !resp.status().is_success() {\n            return Err(anyhow!(\"a API do TikTok respondeu HTTP {}\", resp.status()));\n        }\n        let body = resp.text().await?;\n        if body.trim().is_empty() {\n            return Err(anyhow!(\n                \"a API do TikTok devolveu resposta vazia — normalmente é a sessão expirada ou a \\\n                 assinatura da requisição que o site passou a exigir\"\n            ));\n        }\n        let v: Value = serde_json::from_str(&body)\n            .map_err(|_| anyhow!(\"a resposta da API do TikTok não era JSON\"))?;\n        let (page, next, has_more) = entries_from_item_list(&v);\n        let vazio = page.is_empty();\n        for e in page {\n            if out.len() as u32 >= teto {\n                break;\n            }\n            if !out.iter().any(|x| x.id == e.id) {\n                out.push(e);\n            }\n        }\n        report(\n            progress,\n            ID,\n            \"progress\",\n            out.len() as u64,\n            None,\n            Some(format!(\"{} itens\", out.len())),\n        );","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/tiktok/favorites.rs#L381-L417","documentation":"After a non-empty response, list_private() parses the body as serde_json::Value; when parsing fails (HTML error page, garbled bytes, JSONP wrapper) it raises this anyhow error. TikTok normally returns strict JSON, so non-JSON content signals interception or an API change.","triggerScenarios":"The item-list endpoint returns 2xx non-empty content that is not valid JSON — an HTML login/bot-check page, a compressed body decoded incorrectly, or TikTok switching to a JSONP/signed envelope.","commonSituations":"Anti-bot systems returning an HTML challenge with 200; region-redirect page; a middlebox mangling the response; library outdated after a TikTok API format change.","solutions":["Log the first ~200 bytes of the body to see if it is HTML (login/captcha page) — refresh cookies if so.","Ensure the reqwest client is not disabling gzip/brotli handling that could yield undecoded bytes.","Retry later or from a different IP to rule out a transient anti-bot challenge.","If TikTok changed the response envelope, update the request/parse code in this module."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"fn is_json(body: &str) -> bool { serde_json::from_str::<serde_json::Value>(body).is_ok() }","tryCatchPattern":"match run(opts).await {\n    Ok(entries) => render(entries),\n    Err(e) if e.to_string().contains(\"não era JSON\") => {\n        eprintln!(\"Resposta não-JSON (anti-bot?) — tente novamente com cookies novos\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Log response snippets on failure to quickly identify HTML challenge pages.","Keep the HTTP client defaults for compression handling (gzip/brotli) intact.","Rotate IPs or wait out transient anti-bot challenges.","Update the library when TikTok changes its response envelope."],"tags":["tiktok","json","invalid-response","anti-bot","rust"],"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-15T23:17:13.987Z"}