henrygd/beszel · error
(%d) failed to send download file request
Error message
(%d) failed to send download file request
What it means
downloadFile streams the release asset to a destination path. Because http.Client doesn't treat non-2xx responses as errors, the library checks the status itself and returns this error (with the status code) when the asset download request fails with >= 400. Unlike the releases-list error, the response body is not included, only the status code.
Source
Thrown at internal/ghupdate/ghupdate.go:298
useMirror bool,
) error {
if useMirror {
url = strings.Replace(url, "github.com", "gh.beszel.dev", 1)
}
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
res, err := client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
// http.Client doesn't treat non 2xx responses as error
if res.StatusCode >= 400 {
return fmt.Errorf("(%d) failed to send download file request", res.StatusCode)
}
// ensure that the dest parent dir(s) exist
if err := os.MkdirAll(filepath.Dir(destPath), os.ModePerm); err != nil {
return err
}
dest, err := os.Create(destPath)
if err != nil {
return err
}
defer dest.Close()
if _, err := io.Copy(dest, res.Body); err != nil {
return err
}
return nilView on GitHub (pinned to b38fb7dafa)
Solutions
- Check the status code in the error: 404 means the expected asset name doesn't exist — verify the release on GitHub has an asset matching your OS/arch naming.
- Fix or extend the asset-name matching so the correct artifact is selected for your platform.
- Authenticate requests to avoid 403 rate limits, and wait out the limit if already hit.
- Retry later if the release was just published (assets may still be propagating).
Example fix
// before: release tagged v2.0 lacks a linux-arm64 asset $ ./myapp update // (404) failed to send download file request // after: pin/verify the release contains your platform's asset, or skip $ gh release view v2.0 --json assets # confirm asset exists, then retry update
Defensive patterns
Strategy: retry
Validate before calling
// verify the release has an asset for this platform before downloading
GOOS := runtime.GOOS; GOARCH := runtime.GOARCH
for _, a := range rel.Assets {
if strings.Contains(a.GetName(), GOOS) && strings.Contains(a.GetName(), GOARCH) {
found = true
}
}
if !found { return fmt.Errorf("no asset for %s/%s in %s", GOOS, GOARCH, rel.GetTagName()) } Type guard
func isNotFoundErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "(404)")
} Try / catch
if err := updater.Update(ctx, rel); err != nil {
if strings.Contains(err.Error(), "failed to send download file request") {
if strings.Contains(err.Error(), "(403)") { waitForRateLimitReset(); return retry() }
if strings.Contains(err.Error(), "(404)") { return fmt.Errorf("asset missing for this platform: %w", err) }
return retry()
}
return err
} Prevention
- Confirm each release publishes assets for all supported OS/arch pairs (CI release job).
- Handle 403 rate limits with token auth and backoff.
- Don't re-tag releases; published asset URLs must remain stable.
- Skip update gracefully (log + continue) when the platform asset is absent.
When it happens
Trigger: Calling update (which calls downloadFile) when the asset URL responds 4xx/5xx — typically 404 because the release has no matching asset for the current OS/arch, 403 rate limiting, or an expired/removed release asset URL.
Common situations: New release published without an asset for your platform (wrong asset naming pattern); asset deleted or release re-tagged after publishing; GitHub API rate limit on repeated update checks; private repo asset requiring authentication.
Related errors
- http get: %w
- (%d) failed to fetch latest releases: %s
- unexpected HTTP status: %s
- write tmp: %w
- no websocket connection
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/84a81ab917a54860.
Report an issue: GitHub.