{"record":{"id":"caa9cc1aecf80f3a","repo":"siyuan-note/siyuan","slug":"get-github-releases-failed-d","errorCode":null,"errorMessage":"get GitHub releases failed: %d","messagePattern":"get GitHub releases failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/updater_release.go","lineNumber":247,"sourceCode":"\t\treturn nil, err\n\t}\n\treturn value.([]*githubRelease), nil\n}\n\nfunc fetchGitHubReleases(ctx context.Context) ([]*githubRelease, error) {\n\treleases := []*githubRelease{}\n\trequest := httpclient.NewCloudRequest30s().\n\t\tSetContext(ctx).\n\t\tSetHeader(\"Accept\", \"application/vnd.github+json\").\n\t\tSetHeader(\"X-GitHub-Api-Version\", \"2022-11-28\").\n\t\tSetSuccessResult(&releases)\n\tresponse, err := request.Get(githubReleasesURL)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"get GitHub releases failed: %s\", err)\n\t\treturn nil, err\n\t}\n\tif 200 != response.StatusCode {\n\t\terr = fmt.Errorf(\"get GitHub releases failed: %d\", response.StatusCode)\n\t\tlogging.LogError(err.Error())\n\t\treturn nil, err\n\t}\n\tif 0 == len(releases) {\n\t\treturn nil, errors.New(\"GitHub releases are empty\")\n\t}\n\n\tgithubReleasesLock.Lock()\n\tcachedGitHubReleases = releases\n\tgithubReleasesCacheTime = time.Now().Unix()\n\tgithubReleasesLock.Unlock()\n\treturn releases, nil\n}\n\nfunc selectGitHubRelease(releases []*githubRelease, channel string) *githubRelease {\n\tvar selected *githubRelease\n\tfor _, release := range releases {\n\t\tif nil == release || release.Draft || !isReleaseAllowed(channel, release.TagName) {","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/updater_release.go#L229-L265","documentation":"fetchGitHubReleases performs a GET on the GitHub releases API (api.github.com/repos/siyuan-note/siyuan/releases). When the HTTP request succeeds transport-wise but GitHub replies with a non-200 status, the call fails with 'get GitHub releases failed: <status>'. This surfaces GitHub-side rejections such as rate limiting or API version problems.","triggerScenarios":"Any update check on a non-stable channel when the GitHub API responds 403 (rate limit exhausted for the egress IP), 404, 5xx, or any non-200 status during fetchGitHubReleases.","commonSituations":"CI servers or shared NAT egress hitting GitHub's unauthenticated 60 req/hour rate limit; corporate proxies returning 403/502; GitHub API incidents/outages; blocked network regions returning intermediary status codes.","solutions":["Check the status code in the log: 403 means rate-limited — wait for the limit window to reset or use authenticated network egress","Retry with force=false to use the 6-hour cached release list if one exists","Test the URL https://api.github.com/repos/siyuan-note/siyuan/releases manually from the affected machine to inspect the actual response","Switch to the stable update channel, which uses the cloud Rhy endpoint instead of the GitHub API, or check for updates later"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"resp, err := http.Get(githubReleasesURL)\nif err != nil || resp.StatusCode == 403 {\n    // likely rate limited: delay or skip the check\n}","typeGuard":null,"tryCatchPattern":"releases, err := fetchGitHubReleases(ctx)\nvar rateLimited bool\nif err != nil && strings.Contains(err.Error(), \"403\") {\n    rateLimited = true // back off exponentially, use cache\n}","preventionTips":["Respect the unauthenticated GitHub API limit (60 req/h per IP); rely on the built-in 6h cache and avoid force=true in loops","Serve shared/CI environments with authenticated egress or a caching proxy","Check the logged status code: 403 = rate limit, 5xx = GitHub-side","Fall back to the stable channel when GitHub API access is unreliable"],"tags":["github-api","http","rate-limit","network"],"backgroundTag":"http-error-response","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}