{"record":{"id":"a0de4419575407ba","repo":"jeessy2/ddns-go","slug":"could-not-download-release-from-s-response-code","errorCode":null,"errorMessage":"could not download release from %s. Response code: %d","messagePattern":"could not download release from (.+?)\\. Response code: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/update/package.go","lineNumber":72,"sourceCode":"// cmdPath 是命令可执行文件的文件路径。\nfunc to(assetURL, assetFileName, cmdPath string) error {\n\tsrc, err := downloadAssetFromURL(assetURL)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer src.Close()\n\treturn decompressAndUpdate(src, assetFileName, cmdPath)\n}\n\nfunc downloadAssetFromURL(url string) (rc io.ReadCloser, err error) {\n\tclient := util.CreateHTTPClient()\n\tresp, err := client.Get(url)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not download release from %s: %v\", url, err)\n\t}\n\tif resp.StatusCode >= 300 {\n\t\tresp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"could not download release from %s. Response code: %d\", url, resp.StatusCode)\n\t}\n\n\treturn resp.Body, nil\n}\n","sourceCodeStart":54,"sourceCodeEnd":77,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/util/update/package.go#L54-L77","documentation":"The HTTP-status branch of downloadAssetFromURL: after a successful client.Get, any status code >= 300 causes the body to be closed and this error returned with the URL and code. Unlike error 81, the server responded but refused the download (redirect not followed, 403/404 rate limit, 5xx, etc.).","triggerScenarios":"client.Get(url) succeeded but resp.StatusCode >= 300 — e.g. 404 for a removed release asset, 403 rate-limit or private repo, 302 when redirects are disabled, 500 server error. Raised in downloadAssetFromURL, propagated to to().","commonSituations":"Fetching a deleted/renamed GitHub release asset; hitting GitHub API rate limits (403 with X-RateLimit-Remaining: 0); asset URL pointing at a moved release; server maintenance 5xx.","solutions":["Open the URL in a browser or curl -I to confirm the status code and whether the asset still exists.","Update the release/asset URL to the current published location (404/403 case).","Authenticate or wait out the rate limit if the code is 403/429 from GitHub.","Handle 5xx with retry/backoff; check resp.StatusCode explicitly in the caller to give user-facing messages."],"exampleFix":"// before\nrc, err := to(assetURL)\nif err != nil { return err }\n// after\nrc, err := to(assetURL)\nif err != nil {\n\tif strings.Contains(err.Error(), \"Response code: 404\") {\n\t\treturn fmt.Errorf(\"asset %s no longer exists; please check the release page\", assetURL)\n\t}\n\treturn err\n}","handlingStrategy":"validation","validationCode":"// HEAD check before full download\nresp, err := http.Head(assetURL)\nif err != nil {\n\treturn err\n}\nif resp.StatusCode >= 300 {\n\treturn fmt.Errorf(\"asset %s returned %d; check the release page\", assetURL, resp.StatusCode)\n}","typeGuard":null,"tryCatchPattern":"rc, err := to(assetURL)\nif err != nil {\n\tvar statusErr *StatusError // if you introduce a typed error\n\tif errors.As(err, &statusErr) && statusErr.Code == 404 {\n\t\treturn fmt.Errorf(\"release asset removed; pick another version\")\n\t}\n\treturn err\n}","preventionTips":["Verify asset URLs exist (curl -I) before shipping update configs.","Respect GitHub rate limits; authenticate or cache release metadata.","Follow redirects or resolve final URLs when releases move.","Retry 5xx responses with backoff; do not retry 4xx."],"tags":["go","network","http-status","updater"],"backgroundTag":"http-error-status","analyzedSha":"5874c2e6667c69357ab95079421131104bd3fcae","analyzedAt":"2026-09-03T15:41:16.799Z","contentChangedAt":"2026-09-03T15:41:16.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}