MHSanaei/3x-ui · error
panel updater download is empty
Error message
panel updater download is empty
What it means
Returned when the panel updater download completes (io.Copy succeeded) but exactly 0 bytes were written. The server returned HTTP 200 yet sent an empty body, which means the asset URL resolved to an empty file or an intermediary returned an empty 200. It is a data-integrity guard so an empty file is never chmod'd and executed.
Source
Thrown at internal/web/service/panel/panel.go:390
file, err := os.CreateTemp("", "3x-ui-update-*.sh")
if err != nil {
return "", err
}
path := file.Name()
ok := false
defer func() {
_ = file.Close()
if !ok {
_ = os.Remove(path)
}
}()
n, err := io.Copy(file, io.LimitReader(resp.Body, maxPanelUpdaterBytes+1))
if err != nil {
return "", fmt.Errorf("write panel updater: %w", err)
}
if n == 0 {
return "", fmt.Errorf("panel updater download is empty")
}
if n > maxPanelUpdaterBytes {
return "", fmt.Errorf("panel updater exceeds %d bytes", maxPanelUpdaterBytes)
}
if err := file.Chmod(0o700); err != nil {
return "", err
}
ok = true
return path, nil
}
func fetchLatestPanelVersion() (string, error) {
release, err := fetchPanelRelease("")
if err != nil {
return "", err
}
if release.TagName == "" {
return "", fmt.Errorf("latest panel release tag is empty")View on GitHub (pinned to ad32144c42)
Solutions
- curl -sIL the updater asset URL from the same host and confirm a non-zero Content-Length
- Disable or bypass the HTTP proxy configured for outbound updates and retry
- If the release asset itself is empty, wait for a fixed upstream release or download manually
Defensive patterns
Strategy: validation
Validate before calling
// Head the asset before downloading the body
resp, err := client.Head(assetURL)
if err == nil && resp.ContentLength == 0 {
return errors.New("updater asset is empty upstream; refusing download")
}
Try / catch
if _, err := panel.DownloadPanelUpdater(); err != nil {
if strings.Contains(err.Error(), "download is empty") {
// retry once, then report upstream asset problem
}
}
Prevention
- Treat any empty-body 200 from a download endpoint as interception until proven otherwise
- Verify assets with a HEAD request before initiating update flows
- Keep the panel's proxy settings accurate so empty proxy responses are not mistaken for upstream issues
When it happens
Trigger: The updater asset URL responds 200 with Content-Length 0 or a body that closes immediately; a misconfigured reverse proxy or captive portal answering 200 with an empty page; the release asset being uploaded empty.
Common situations: Transparent corporate/NAT proxies that return empty 200s for unknown binaries; a GitHub release where the updater asset failed to upload; redirect chains that end in an empty response.
Related errors
- write panel updater: %w
- panel updater exceeds %d bytes
- download panel updater: unexpected HTTP %d
- latest panel release tag is empty
- download xray: unexpected HTTP %d
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/1ee09836eed176e4.
Report an issue: GitHub.