tonhowtf/omniget · error

Resposta GQL sem data

Error message

Resposta GQL sem data

What it means

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.

Solutions

  1. Log the raw response body on this error to see whether it's a GraphQL errors object, a challenge, or HTML.
  2. Check for a top-level "errors" array in the JSON and surface it to diagnose bad query variables.
  3. Retry with a fresh anonymous cookie/headers, since 200-with-challenge usually indicates bot detection.
  4. Verify the response Content-Type is application/json before parsing; treat HTML bodies as an auth/bot failure instead.

Example fix

// before
let data = json.get("data")
    .ok_or_else(|| anyhow!("Resposta GQL sem data"))?;
// after
if let Some(errs) = json.get("errors") {
    anyhow::bail!("Instagram GQL errors: {}", errs);
}
let data = json.get("data")
    .with_context(|| format!("Resposta GQL sem data; body: {}", serde_json::to_string(&json).unwrap_or_default().chars().take(500).collect::<String>()))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// After parsing, before trusting the shape:
let json: serde_json::Value = serde_json::from_str(&body)?;
anyhow::ensure!(json.is_object(), "GQL response is not a JSON object (got HTML/empty body?)");
anyhow::ensure!(json.get("data").map_or(false, |d| d.is_object()), "GQL response missing data object");

Type guard

fn gql_data_field(json: &serde_json::Value) -> Option<&serde_json::Value> {
    if json.is_object() && json.get("data")?.is_object() { json.get("data") } else { None }
}

Try / catch

match platform.get_media_info(url).await {
    Err(e) if e.to_string().contains("Resposta GQL sem data") => {
        // log raw body, refresh cookies/headers, retry once — often a soft bot-block
        eprintln!("GQL envelope missing; refreshing anon cookie and retrying");
        refresh_anon_cookie().await?;
        platform.get_media_info(url).await
    }
    other => other,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/platforms/instagram.rs:430

            .header("X-CSRFToken", &params.csrf_token)
            .header("X-FB-Friendly-Name", "PolarisPostActionLoadPostQueryQuery")
            .header("x-asbd-id", "129477")
            .header("X-Bloks-Version-Id", &params.bloks_version_id)
            .header("Referer", "https://www.instagram.com/")
            .header("Cookie", &anon_cookie)
            .body(body)
            .send()
            .await?;

        if !response.status().is_success() {
            return Err(anyhow!("Instagram GQL retornou HTTP {}", response.status()));
        }

        let json: serde_json::Value = response.json().await?;

        let data = json
            .get("data")
            .ok_or_else(|| anyhow!("Resposta GQL sem data"))?;

        let media = data
            .get("xdt_shortcode_media")
            .or_else(|| data.get("shortcode_media"));

        match media {
            Some(m) if !m.is_null() => Ok(m.clone()),
            _ => Err(anyhow!("Post not found via GQL")),
        }
    }

    async fn request_embed(&self, post_id: &str) -> anyhow::Result<serde_json::Value> {
        let url = format!("https://www.instagram.com/p/{}/embed/captioned/", post_id);

        let response = self
            .client
            .get(&url)
            .header(

View on GitHub (pinned to 8600b91f42)