matryer/xbar · error

download update

Error message

download update

What it means

This error is wrapped by Updater.Update (pkg/update/update.go:75) when downloadAndReplaceApp fails to download the selected release asset and swap it in for the running application. The update flow (fetch latest release, select asset, download-and-replace) reached the download step but the download, checksum/verify, or file-replacement failed. The wrap marks the failure as occurring during the self-update download phase.

Source

Thrown at pkg/update/update.go:75

		return nil, err
	}
	hasUpdate := hasUpdate(u.CurrentVersion, latest.TagName)
	if !hasUpdate {
		return nil, nil
	}
	var selectedAsset *Asset
	for _, asset := range latest.Assets {
		if u.SelectAsset(*latest, asset) {
			selectedAsset = &asset
			break
		}
	}
	if selectedAsset == nil {
		return nil, errors.New("no asset selected, use SelectAssetFunc to select an asset")
	}
	err = u.downloadAndReplaceApp(*selectedAsset)
	if err != nil {
		return nil, errors.Wrap(err, "download update")
	}
	return latest, nil
}

// Restart spawns the current executable again, and terminates
// the running one.
func (u *Updater) Restart() error {
	time.Sleep(1 * time.Second)
	thisExecuable, err := os.Executable()
	if err != nil {
		return errors.Wrap(err, "get executable")
	}
	log.Println("restarting", thisExecuable)
	cmd := exec.Command(thisExecuable)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Setpgid: false,
	}
	cmd.Dir = filepath.Dir(thisExecuable)

View on GitHub (pinned to d624239058)

Solutions

  1. Check the wrapped cause for HTTP status — 404 means the asset URL is gone; re-cut or re-upload the release asset
  2. Verify network/proxy reachability of the asset URL from the host (curl the URL)
  3. Ensure the executable's directory is writable by the process user (and on Windows that no process/AV holds a lock)
  4. Run the app from a writable location rather than a read-only mount or system directory
  5. Retry the update later; transient network failures are common
  6. Fall back to manual download-and-replace of the binary

Example fix

// before
latest, err := updater.Update()
if err != nil {
	log.Fatal(err)
}
// after
latest, err := updater.Update()
if err != nil {
	if strings.Contains(fmt.Sprintf("%+v", err), "404") {
		log.Println("asset missing upstream; skipping auto-update")
		return
	}
	log.Printf("update failed, retrying in 1h: %v", err)
	time.Sleep(time.Hour)
	latest, err = updater.Update()
	if err != nil {
		log.Fatal(err)
	}
}
Defensive patterns

Strategy: try-catch

Validate before calling

resp, err := http.Head(assetURL)
if err != nil || resp.StatusCode != http.StatusOK {
	return fmt.Errorf("update asset unavailable: status=%v err=%v", resp.StatusCode, err)
}
if dir := filepath.Dir(os.Args[0]); !writable(dir) {
	return fmt.Errorf("install dir %s not writable", dir)
}

Try / catch

latest, err := updater.Update()
if err != nil {
	if strings.Contains(fmt.Sprintf("%+v", err), "download update") {
		log.Printf("auto-update failed, will retry next cycle: %v", err)
		return nil // degrade gracefully; app keeps running current version
	}
	return err
}

Prevention

When it happens

Trigger: Update() runs after SelectAssetFunc picks an asset, then u.downloadAndReplaceApp(*selectedAsset) errors: asset URL unreachable (network down, 404 after a release was deleted), download interrupted, temp-file write/permission failure, or failure replacing the running executable (file locked on Windows / text-file-busy).

Common situations: GitHub release asset removed or renamed so the stored URL 404s; corporate proxy/firewall blocking the download host; running from a directory the user cannot write to; antivirus locking the binary during replacement; running binary mounted read-only; TLS/proxy MITM cert issues in containers.

Related errors


AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02). Data as JSON: /api/errors/61929e220c1be966. Report an issue: GitHub.