tonhowtf/omniget · error

FxTwitter: resposta invalida

Error message

FxTwitter: resposta invalida ({})

What it means

fx.rs's get() calls the FxTwitter API and this error is raised when the HTTP response body cannot be deserialized as JSON. It wraps the serde error message plus the raw payload interpretation, meaning the upstream service returned non-JSON (HTML error page, empty body, gateway error).

Solutions

  1. Retry the request; transient upstream outages are the usual cause.
  2. Log the response text and status before parsing to identify what actually came back.
  3. Check FxTwitter service status / try an alternate API host (e.g. api.fxtwitter.com vs fixupx).
  4. Fall back to a different X data source (the native X client) when FxTwitter is unavailable.

Example fix

// before
let body: Value = resp.json().await
    .map_err(|e| anyhow!("FxTwitter: resposta invalida ({})", e))?;
// after
let text = resp.text().await?;
let body: Value = serde_json::from_str(&text)
    .map_err(|e| anyhow!("FxTwitter: resposta invalida ({}) corpo: {:.200}", e, text))?;
Defensive patterns

Strategy: fallback

Type guard

fn is_json_content(headers: &reqwest::header::HeaderMap) -> bool {
    headers.get(reqwest::header::CONTENT_TYPE)
        .and_then(|v| v.to_str().ok())
        .map_or(false, |v| v.contains("application/json"))
}

Try / catch

match fx::status(&id).await {
    Ok(p) => p,
    Err(e) if e.to_string().starts_with("FxTwitter: resposta invalida") => {
        eprintln!("FxTwitter fora do ar, usando cliente nativo");
        xclient::status(&id).await?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: FxTwitter (or an intermediate proxy/CDN) responds with HTML (502/503 Cloudflare page), an empty body, or truncated output so resp.json() fails during any get()-backed call: status, thread, conversation, profile, profile_statuses, profile_media.

Common situations: FxTwitter outage or Cloudflare challenge page; corporate proxy stripping/rewriting the response; network device injecting a captive-portal page; FxTwitter deployment returning text/plain errors.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/79444c228facebc4. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/x/fx.rs:46

async fn get(path: &str, query: &[(&str, String)]) -> anyhow::Result<Value> {
    let client = client()?;
    let url = format!("{}/{}", BASE, path.trim_start_matches('/'));
    let mut req = client.get(&url);
    let q: Vec<(&str, &str)> = query
        .iter()
        .filter(|(_, v)| !v.is_empty())
        .map(|(k, v)| (*k, v.as_str()))
        .collect();
    if !q.is_empty() {
        req = req.query(&q);
    }
    let resp = req.send().await?;
    let status = resp.status();
    let body: Value = resp
        .json()
        .await
        .map_err(|e| anyhow!("FxTwitter: resposta invalida ({})", e))?;
    let code = body
        .get("code")
        .and_then(|c| c.as_u64())
        .unwrap_or(status.as_u16() as u64);
    if code == 404 {
        return Err(anyhow!("nao encontrado no X (ou o post e privado)"));
    }
    if code == 401 {
        return Err(anyhow!("post ou perfil privado"));
    }
    if code == 429 {
        return Err(anyhow!(
            "FxTwitter: limite de requisicoes atingido, tente de novo em instantes"
        ));
    }
    if code >= 400 {
        let msg = body
            .get("message")

View on GitHub (pinned to 8600b91f42)