tonhowtf/omniget · error · anyhow::Error
Twitch GQL: {}
Error message
Twitch GQL: {} What it means
The public anonymous query helper checks the GQL response for a GraphQL `errors` array (via first_error) and, if present, wraps the first error message in this error. HTTP succeeded, but Twitch rejected the operation at the GraphQL level — bad query syntax, unknown fields, or a data-layer error such as a nonexistent resource. It surfaces the server-side GraphQL error text directly to the caller.
Solutions
- Read the message text — it contains Twitch's own GraphQL error, usually naming the offending field or problem.
- Validate the query against the current Twitch GQL schema (introspection or a GQL playground) and fix removed/renamed fields.
- Check the entity being queried (channel login, video/clip id) actually exists and is public.
- If Twitch rotated its schema, update the query strings in channel/video/clip_video to the new shape.
- Consider adding fallback logic that inspects the full `errors` array instead of only the first message.
Example fix
// before
if let Some(msg) = first_error(&json) {
bail!("Twitch GQL: {}", msg);
}
// after
if let Some(msg) = first_error(&json) {
bail!("Twitch GQL: {} (query: {}...)", msg, &query[..query.len().min(80)]);
} Defensive patterns
Strategy: try-catch
Validate before calling
// check the entity exists / query is non-empty before calling
if query.trim().is_empty() { anyhow::bail!("empty GQL query"); } Try / catch
match gql.query(&q).await {
Err(e) if e.to_string().starts_with("Twitch GQL:") => {
// GraphQL-level failure: parse message, fix schema fields or entity id
}
other => other,
} Prevention
- Lint GraphQL queries against Twitch's current schema in CI (schema diff or gql lint).
- Verify channel/video/clip identifiers exist and are public before querying.
- Treat Twitch GQL schema drift as a maintenance item; pin known-good query strings.
- Inspect the full `errors` array, not just the first message, when debugging.
When it happens
Trigger: Calling GqlClient::query with a query string that Twitch accepts over HTTP but fails to execute — unknown field/operation, syntax error in the query, variables mismatch, or entity not found — causing a non-empty `errors` array in the JSON response.
Common situations: Twitch renamed/removed fields from its public GQL schema so channel/video/clip queries reference nonexistent fields; typos in hand-written GraphQL strings; querying private/deleted channels or videos; using a persisted operation shape with the anonymous query endpoint.
Related errors
- Twitch GQL respondeu HTTP {}
- Twitch recusou o replay de chat: {}
- resposta do Twitch GQL sem `data`
- Grok: nao consegui abrir uma conversa
- No video quality available
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/a2e906606b20e974.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/tools/twitch/gql.rs:177
let status = resp.status();
if status.as_u16() == 429 || status.is_server_error() {
last = format!("HTTP {}", status);
continue;
}
if !status.is_success() {
bail!("Twitch GQL respondeu HTTP {}", status);
}
return Ok(resp.json::<Value>().await?);
}
bail!("Twitch GQL não respondeu depois de 5 tentativas: {}", last)
}
/// Query anônima em texto (as públicas aceitam sem persisted query).
pub async fn query(&self, query: &str) -> anyhow::Result<Value> {
let body = json!({ "query": query });
let json = self.post(&body).await?;
if let Some(msg) = first_error(&json) {
bail!("Twitch GQL: {}", msg);
}
json.get("data")
.cloned()
.ok_or_else(|| anyhow!("resposta do Twitch GQL sem `data`"))
}
/// Persisted query (formato em lote, como o site manda). Devolve o
/// primeiro elemento cru, para quem quiser ler `errors` também.
pub async fn persisted(&self, op: &str, hash: &str, vars: Value) -> anyhow::Result<Value> {
let body = json!([{
"operationName": op,
"variables": vars,
"extensions": { "persistedQuery": { "version": 1, "sha256Hash": hash } },
}]);
let json = self.post(&body).await?;
json.as_array()
.and_then(|a| a.first())
.cloned()View on GitHub (pinned to 8600b91f42)