tonhowtf/omniget · error

xAI: resposta invalida

Error message

xAI: resposta invalida ({})

What it means

ask_xai() called the xAI API and the HTTP response body could not be deserialized as JSON, so the serde error is wrapped into this message. This indicates the xAI endpoint (or a proxy) returned non-JSON content such as an HTML error page or an empty body.

Solutions

  1. Verify the xAI API base URL includes the correct path (https://api.x.ai/v1).
  2. Capture and log resp.text() before parsing to see the actual payload.
  3. Retry on transient gateway errors (502/503 pages are HTML).
  4. Check for proxy/VPN interference and network reachability to api.x.ai.

Example fix

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

Strategy: retry

Validate before calling

// preflight da URL e da chave
let base = std::env::var("XAI_BASE_URL").unwrap_or_else(|_| "https://api.x.ai/v1".into());
if !base.starts_with("https://api.x.ai") {
    eprintln!("aviso: base URL incomum para xAI: {base}");
}

Try / catch

match grok::ask(prompt).await {
    Ok(a) => a,
    Err(e) if e.to_string().starts_with("xAI: resposta invalida") => {
        tokio::time::sleep(Duration::from_secs(3)).await;
        grok::ask(prompt).await // gateway pages are usually transient
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: xAI's chat endpoint returns HTML/empty/non-JSON (gateway timeout page, wrong base URL pointing at a website, proxy interception) during the ask flow.

Common situations: Misconfigured XAI base URL (e.g. missing /v1 or pointing to the console site); corporate proxy or captive portal; xAI outage serving non-JSON errors; response stream truncated mid-body.

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/58cb51e307fa58ca. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/x/grok.rs:192

        body["instructions"] = json!(req.system.trim());
    }
    if !tools.is_empty() {
        body["tools"] = json!(tools);
    }
    let client = crate::core::http_client::apply_global_proxy(reqwest::Client::builder())
        .timeout(std::time::Duration::from_secs(180))
        .build()?;
    let resp = client
        .post("https://api.x.ai/v1/responses")
        .bearer_auth(&cfg.xai_key)
        .json(&body)
        .send()
        .await?;
    let status = resp.status();
    let v: Value = resp
        .json()
        .await
        .map_err(|e| anyhow!("xAI: resposta invalida ({})", e))?;
    if !status.is_success() {
        let msg = v
            .pointer("/error/message")
            .or_else(|| v.get("error"))
            .and_then(|m| m.as_str())
            .unwrap_or("erro")
            .to_string();
        return Err(anyhow!("xAI HTTP {}: {}", status, msg));
    }
    let mut text = String::new();
    let mut citations: Vec<Citation> = Vec::new();
    for item in v
        .get("output")
        .and_then(|o| o.as_array())
        .into_iter()
        .flatten()
    {
        if item.get("type").and_then(|t| t.as_str()) != Some("message") {

View on GitHub (pinned to 8600b91f42)