{"record":{"id":"f2be52a8fd3f758f","repo":"jesseduffield/lazygit","slug":"graphql-query-failed-with-status-s-body-s","errorCode":null,"errorMessage":"GraphQL query failed with status: %s. Body: %s","messagePattern":"GraphQL query failed with status: (.+?)\\. Body: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/commands/git_commands/github.go","lineNumber":292,"sourceCode":"\t}\n\n\treq.Header.Set(\"Authorization\", \"token \"+token)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\t// Bound the request so that a dead or extremely slow network can't leave\n\t// the pull-request refresh in flight for minutes. The data is auxiliary,\n\t// so giving up and retrying on the next refresh beats waiting.\n\tclient := &http.Client{Timeout: 10 * time.Second}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tbodyStr := new(bytes.Buffer)\n\t\t_, _ = bodyStr.ReadFrom(resp.Body)\n\t\treturn nil, fmt.Errorf(\"GraphQL query failed with status: %s. Body: %s\", resp.Status, bodyStr.String())\n\t}\n\n\trespBytes, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn parsePullRequestsResponse(respBytes)\n}\n\nfunc parsePullRequestsResponse(respBytes []byte) ([]*models.GithubPullRequest, error) {\n\tvar result Response\n\tif err := json.Unmarshal(respBytes, &result); err != nil {\n\t\treturn nil, err\n\t}\n\n\tprs := []*models.GithubPullRequest{}\n\tfor _, repoQuery := range result.Data.Repository {","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/jesseduffield/lazygit/blob/c477a2959b229fbf3284be0d4d2904ab61ec3c94/pkg/commands/git_commands/github.go#L274-L310","documentation":"The GitHub integration sends a GraphQL query (pull requests for the current repo) with a 10-second HTTP timeout; any non-200 response is turned into this error including the HTTP status and response body. Because the data is auxiliary, lazygit surfaces it but recovers on the next PR refresh rather than crashing.","triggerScenarios":"HTTP 401 (bad/expired stored GitHub token), 403/429 rate limiting, 5xx GitHub outages, or a proxy returning an error page — any non-OK status from api.github.com/graphql.","commonSituations":"Overusing the PR view beyond GitHub's API quota; a revoked OAuth token after re-authenticating elsewhere; corporate proxies injecting error bodies; GitHub incidents.","solutions":["Read the embedded body: it states the cause (rate limit reset time, 'Bad credentials', etc.).","For 401, re-authenticate: remove the stored token (config/credentials) and let lazygit re-do the OAuth flow.","For 403/429, wait for the rate-limit window to reset; reduce refresh frequency.","For 5xx/proxy issues, verify with 'curl -H \"Authorization: bearer <token>\" https://api.github.com/graphql' from the same network."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-check auth/rate-limit cheaply before the GraphQL call:\nresp, err := http.Get(\"https://api.github.com/rate_limit\") // with auth header\nif err == nil && resp.StatusCode == 401 {\n    return errors.New(\"token invalid; re-authenticate\")\n}\n_ = resp.Body.Close()","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var sb strings.Builder\n    if strings.Contains(err.Error(), \"GraphQL query failed with status:\") {\n        // auxiliary data: log and continue; next PR refresh retries\n        log.Warn(err)\n        return nil, err // non-fatal at UI layer\n    }\n    return err\n}","preventionTips":["Keep the stored GitHub token fresh; re-run the OAuth flow on 401.","Cache PR responses and rate-limit refreshes to stay under quota.","Treat PR data as best-effort in your UI so transient GitHub errors degrade gracefully."],"tags":["github","graphql","network","rate-limit","api"],"backgroundTag":null,"analyzedSha":"c477a2959b229fbf3284be0d4d2904ab61ec3c94","analyzedAt":"2026-08-15T08:34:32.451Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}