{"record":{"id":"6ec05fde8e1acc0f","repo":"spicetify/cli","slug":"github-response-release-message","errorCode":null,"errorMessage":"GitHub response: {{release.Message}}","messagePattern":"GitHub response: (.+?)\\}","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/utils/vcs.go","lineNumber":32,"sourceCode":"\nfunc FetchLatestTag() (string, error) {\n\tres, err := http.Get(\"https://api.github.com/repos/spicetify/cli/releases/latest\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tbody, err := io.ReadAll(res.Body)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tvar release GithubRelease\n\tif err = json.Unmarshal(body, &release); err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif release.TagName == \"\" {\n\t\treturn \"\", errors.New(\"GitHub response: \" + release.Message)\n\t}\n\n\treturn release.TagName[1:], nil\n}\n","sourceCodeStart":14,"sourceCodeEnd":37,"githubUrl":"https://github.com/spicetify/cli/blob/1f13f736163165234eef4fb792a03f9b5b732aa4/src/utils/vcs.go#L14-L37","documentation":"FetchLatestTag queries the GitHub releases API and unmarshals the JSON into a GithubRelease. If the response has no tag_name, the library assumes GitHub returned an error payload and surfaces the API's message field verbatim in this error. It means the HTTP call succeeded (200) but the body is an API error object rather than a release.","triggerScenarios":"Calling FetchLatestTag against a repository with no releases, or hitting rate limits / bad tokens where GitHub returns 200-family or JSON bodies containing message but no tag_name.","commonSituations":"GitHub API rate limiting from CI (unauthenticated requests exhausted); renamed/moved upstream repo; running a fork with no releases published; corporate proxy returning a JSON error page.","solutions":["Read the embedded release.Message to see GitHub's actual reason (e.g. Not Found vs rate limit).","If rate limited, set a GITHUB_TOKEN or wait for the rate-limit window to reset.","Verify the repository/owner in the request URL still exists and has published releases.","Retry later if GitHub is having an incident."],"exampleFix":"// before\ntag, err := utils.FetchLatestTag()\n// after\ntag, err := utils.FetchLatestTag()\nif err != nil && strings.Contains(err.Error(), \"API rate limit\") {\n    // retry with authenticated client or later\n}","handlingStrategy":"try-catch","validationCode":"// Check quota before calling\nresp, _ := http.Get(\"https://api.github.com/rate_limit\")\n// parse resources.core.remaining; if 0, wait before FetchLatestTag","typeGuard":null,"tryCatchPattern":"tag, err := utils.FetchLatestTag()\nif err != nil {\n    if strings.Contains(err.Error(), \"API rate limit\") {\n        // back off / authenticate\n    } else if strings.Contains(err.Error(), \"Not Found\") {\n        // repo has no releases\n    }\n    return err\n}","preventionTips":["Use authenticated GitHub API requests in CI to avoid rate limits.","Confirm the target repo publishes releases before calling.","Handle GitHub API message payloads defensively instead of assuming tag_name."],"tags":["network","github-api","http"],"backgroundTag":"github-api-error-response","analyzedSha":"1f13f736163165234eef4fb792a03f9b5b732aa4","analyzedAt":"2026-08-31T18:57:59.754Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}