spicetify/cli · error

unexpected HTTP status: %s for %s

Error message

unexpected HTTP status: %s for %s

What it means

During Update, spicetify downloads the latest release asset and expects HTTP 200. If the download response status is anything else it closes the body/file, fails the spinner, and calls utils.Fatal with this error naming the status and asset URL. It means the release asset could not be downloaded at that URL.

Source

Thrown at src/cmd/update.go:69

	out, err := os.Create(location)
	if err != nil {
		spinner.Fail("Failed to download Spicetify")
		utils.Fatal(err)
	}
	defer out.Close()

	resp2, err := http.Get(assetURL)
	if err != nil {
		out.Close()
		spinner.Fail("Failed to download Spicetify")
		utils.Fatal(err)
	}

	if resp2.StatusCode != http.StatusOK {
		resp2.Body.Close()
		out.Close()
		spinner.Fail("Failed to download Spicetify")
		utils.Fatal(fmt.Errorf("unexpected HTTP status: %s for %s", resp2.Status, assetURL))
	}

	defer resp2.Body.Close()

	_, err = io.Copy(out, resp2.Body)
	if err != nil {
		resp2.Body.Close()
		out.Close()
		spinner.Fail("Failed to download Spicetify")
		utils.Fatal(err)
	}
	spinner.Success("Downloaded Spicetify")

	exe, err := os.Executable()
	if err != nil {
		utils.Fatal(err)
	}
	if exe, err = filepath.EvalSymlinks(exe); err != nil {

View on GitHub (pinned to 1f13f73616)

Solutions

  1. Retry the update; CDN 5xx/429 issues are often transient.
  2. Check the assetURL printed in the error manually in a browser to confirm it 404s or is blocked.
  3. If rate limited, authenticate requests with a GITHUB_TOKEN or wait for the limit reset.
  4. Update via an alternative channel (package manager, manual download of the release asset) if the proxy blocks GitHub.
  5. Verify spicetify version supports the current upstream release layout (asset name changes cause 404s).

Example fix

// before
if resp2.StatusCode != http.StatusOK {
    utils.Fatal(fmt.Errorf("unexpected HTTP status: %s for %s", resp2.Status, assetURL))
}
// after (caller-side retry)
for i := 0; i < 3; i++ {
    if err := tryUpdate(); err == nil { break }
    time.Sleep(5 * time.Second)
}
Defensive patterns

Strategy: retry

Validate before calling

// Preflight: HEAD the asset URL
resp, err := http.Head(assetURL)
if err == nil && resp.StatusCode != http.StatusOK {
    return fmt.Errorf("asset unavailable: %s", resp.Status)
}

Try / catch

err := runUpdate()
if err != nil && strings.Contains(err.Error(), "unexpected HTTP status") {
    time.Sleep(10 * time.Second)
    err = runUpdate() // retry once for transient 5xx/429
}

Prevention

When it happens

Trigger: Update() performs the asset download request (resp2) and resp2.StatusCode != http.StatusOK — e.g. 403 (rate limit/expired URL), 404 (asset renamed/removed), 302-followed-to-error, or 5xx from the CDN.

Common situations: GitHub rate limiting in CI; upstream release re-replaced and old asset URL 404s; corporate proxy blocking github release CDN (objects.githubusercontent.com); transient GitHub outage.

Related errors


AI-assisted analysis of spicetify/cli@1f13f73616 (2026-08-31). Data as JSON: /api/errors/0b428129e66c3f13. Report an issue: GitHub.