{"record":{"id":"b59ff2dd4a1928a0","repo":"github/github-mcp-server","slug":"failed-to-get-latest-release-w","errorCode":null,"errorMessage":"failed to get latest release: %w","messagePattern":"failed to get latest release: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/github/repositories.go","lineNumber":1955,"sourceCode":"\t\t[]scopes.Scope{scopes.Repo},\n\t\tfunc(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {\n\t\t\towner, err := RequiredParam[string](args, \"owner\")\n\t\t\tif err != nil {\n\t\t\t\treturn utils.NewToolResultError(err.Error()), nil, nil\n\t\t\t}\n\t\t\trepo, err := RequiredParam[string](args, \"repo\")\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\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\trelease, resp, err := client.Repositories.GetLatestRelease(ctx, owner, repo)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to get latest release: %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 get latest release\", resp, body), nil, nil\n\t\t\t}\n\n\t\t\tr, err := json.Marshal(release)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to marshal response: %w\", err)\n\t\t\t}\n\n\t\t\tresult := utils.NewToolResultText(string(r))\n\t\t\t// Releases are published by collaborators with push access, so","sourceCodeStart":1937,"sourceCodeEnd":1973,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/repositories.go#L1937-L1973","documentation":"Returned by get_latest_release when client.Repositories.GetLatestRelease (GET /repos/{owner}/{repo}/releases/latest) fails. GitHub answers 404 both for an unknown repo and - very commonly - for a repo that simply has no published (non-draft) release yet, so 404 is the dominant trigger. The handler wraps with a bare fmt.Errorf instead of the structured ghErrors mapping used by neighbors, so the status code lives only in the wrapped *github.ErrorResponse; 401 (expired token) and 403 (rate limit) also surface here.","triggerScenarios":"Repo exists but has zero published releases (404 'Not Found'); only draft or prerelease-unpublished entries exist, since the latest endpoint never returns drafts; unknown/private-to-token repo (404); expired or revoked token (401); rate limit exhausted (403).","commonSituations":"Calling get_latest_release on a brand-new project before its first release; repos whose releases are all drafts; wrong owner/repo; CI token quota exhausted.","solutions":["Confirm a published release exists: `gh api repos/OWNER/REPO/releases --jq '[.[] | select(.draft==false)] | length'`.","If zero: switch to list_releases and treat the empty list as 'no releases'.","404 despite releases: fix owner/repo spelling or grant the token repo access.","401/403: refresh the token / wait out the rate-limit window."],"exampleFix":"// caller: treat 404 as 'no release yet' instead of a hard failure\nconst res = await client.callTool({ name: 'get_latest_release', arguments: { owner, repo } });\nif (res.isError && /failed to get latest release/.test(JSON.stringify(res.content))) {\n  const list = await client.callTool({ name: 'list_releases', arguments: { owner, repo } });\n  // parse list; empty -> report 'no published releases'\n}","handlingStrategy":"validation","validationCode":"# get_latest_release 404s until a non-draft release exists - check first\ngh api 'repos/OWNER/REPO/releases?per_page=100' --jq '[.[] | select(.draft == false)] | length'\n# 0 -> skip get_latest_release; call list_releases and treat [] as 'no releases'","typeGuard":null,"tryCatchPattern":"const res: any = await client.callTool({ name: 'get_latest_release', arguments: { owner, repo } });\nif (res.isError && /failed to get latest release/.test(JSON.stringify(res.content))) {\n  // 404 is expected for repos with no published release - fall back\n  const list: any = await client.callTool({ name: 'list_releases', arguments: { owner, repo } });\n}","preventionTips":["Publish at least one release before wiring get_latest_release into pipelines.","Treat 404 from this endpoint as 'no latest release', not an error path.","Validate owner/repo with a cheap repo GET before release automation.","Watch rate-limit headers when checking releases in loops."],"tags":["go","github-api","releases","http","not-found"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}