{"record":{"id":"57f7a1488f9df93d","repo":"github/github-mcp-server","slug":"failed-to-list-releases-w","errorCode":null,"errorMessage":"failed to list releases: %w","messagePattern":"failed to list releases: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/github/repositories.go","lineNumber":1852,"sourceCode":"\t\t\t}\n\t\t\tpagination, err := OptionalPaginationParams(args)\n\t\t\tif err != nil {\n\t\t\t\treturn utils.NewToolResultError(err.Error()), nil, nil\n\t\t\t}\n\n\t\t\topts := &github.ListOptions{\n\t\t\t\tPage:    pagination.Page,\n\t\t\t\tPerPage: pagination.PerPage,\n\t\t\t}\n\n\t\t\tclient, err := deps.GetClient(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to get GitHub client: %w\", err)\n\t\t\t}\n\n\t\t\treleases, resp, err := client.Repositories.ListReleases(ctx, owner, repo, opts)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to list releases: %w\", err)\n\t\t\t}\n\t\t\tdefer func() { _ = resp.Body.Close() }()\n\n\t\t\tif resp.StatusCode != http.StatusOK {\n\t\t\t\tbody, err := io.ReadAll(resp.Body)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to read response body: %w\", err)\n\t\t\t\t}\n\t\t\t\treturn ghErrors.NewGitHubAPIStatusErrorResponse(ctx, \"failed to list releases\", resp, body), nil, nil\n\t\t\t}\n\n\t\t\tminimalReleases := make([]MinimalRelease, 0, len(releases))\n\t\t\tfor _, release := range releases {\n\t\t\t\tif release != nil {\n\t\t\t\t\tminimalReleases = append(minimalReleases, convertToMinimalRelease(release))\n\t\t\t\t}\n\t\t\t}\n","sourceCodeStart":1834,"sourceCodeEnd":1870,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/repositories.go#L1834-L1870","documentation":"Returned by list_releases when client.Repositories.ListReleases (GET /repos/{owner}/{repo}/releases) itself fails. Unlike every neighboring call in this file, the handler wraps it with a bare fmt.Errorf instead of ghErrors.NewGitHubAPIErrorResponse, so the structured status/message from go-github's *github.ErrorResponse survives only inside the %w chain. Triggers: 404 (repo unknown or invisible to the token), 401 (bad token), 403 (rate limit or forbidden), and pure network failures where the call never completes.","triggerScenarios":"Listing releases on a nonexistent repo (404); a fine-grained PAT without access to the private repo (404/403); primary rate limit exhausted (403 'API rate limit exceeded'); expired token (401); DNS/TLS failure reaching api.github.com.","commonSituations":"Typo'd owner/repo; pointing the tool at a fork or private repo the token cannot see; CI jobs exhausting token quota mid-run; GHES host unreachable.","solutions":["Reproduce with the same token: `gh api repos/OWNER/REPO/releases --jq length` shows the raw 404/403/401 directly.","404: fix owner/repo spelling or grant the token access to the repo.","403 rate limit: check `gh api rate_limit`, wait for reset, retry with backoff.","401: rotate/refresh the token.","Persistent: read the wrapped *github.ErrorResponse.Message in server logs for the exact cause."],"exampleFix":"// before\nreleases, resp, err := client.Repositories.ListReleases(ctx, owner, repo, opts)\nif err != nil {\n\treturn nil, nil, fmt.Errorf(\"failed to list releases: %w\", err)\n}\n\n// after: structured API error like every neighboring handler\nreleases, resp, err := client.Repositories.ListReleases(ctx, owner, repo, opts)\nif err != nil {\n\treturn ghErrors.NewGitHubAPIErrorResponse(ctx, \"failed to list releases\", resp, err), nil, nil\n}","handlingStrategy":"try-catch","validationCode":"# same token as the MCP server uses\ngh api 'repos/OWNER/REPO/releases?per_page=1' --jq 'length'  # 404 -> repo invisible to token\ngh api rate_limit --jq '.resources.core.remaining'            # 0 -> expect 403 failures","typeGuard":null,"tryCatchPattern":"// when embedding the handler's client\nreleases, resp, err := client.Repositories.ListReleases(ctx, owner, repo, opts)\nif err != nil {\n\tvar ghErr *github.ErrorResponse\n\tif errors.As(err, &ghErr) {\n\t\tswitch ghErr.Response.StatusCode {\n\t\tcase http.StatusNotFound: // unknown repo or token lacks access\n\t\tcase http.StatusUnauthorized: // expired/revoked token\n\t\tcase http.StatusForbidden: // rate limit - back off until reset\n\t\t}\n\t}\n}","preventionTips":["Verify owner/repo exist and are visible to the token before bulk jobs.","Check rate_limit ahead of release-heavy automation.","Use per_page<=100 and paginate instead of hammering large repos.","Parse the wrapped *github.ErrorResponse rather than string matching when possible."],"tags":["go","github-api","http","rate-limit","releases"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}