coreybutler/nvm-windows · error

error: received status code %d

Error message

error: received status code %d

What it means

The get() helper behind every upgrade HTTP request returns this error when the server responds with any status other than 200 OK. It discards the body and reports only the code, so '403', '404', or '429' all surface through this one message. It is the shared failure point for version checks, zip downloads, checksum downloads, and asset downloads.

Source

Thrown at src/upgrade/upgrade.go:728

	}

	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return []byte{}, err
	}
	req.Header.Set("User-Agent", "nvm-windows")
	req.Header.Set("Cache-Control", "no-cache")
	req.Header.Set("Pragma", "no-cache")

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return []byte{}, fmt.Errorf("error: received status code %d", resp.StatusCode)
	}

	return io.ReadAll(resp.Body)
}

func checkForUpdate(url string) (*Update, error) {
	u := Update{Assets: []string{}, Warnings: []string{}, VersionWarnings: []string{}}
	r := Release{}

	// Make the HTTP GET request
	utility.DebugLogf("checking for updates at %s", url)
	body, err := get(url, false)
	if err != nil {
		return &u, fmt.Errorf("error: reading response body: %v", err)
	}

	// Parse JSON into the struct
	utility.DebugLogf("Received:\n%s", string(body))

View on GitHub (pinned to 5b18223ca1)

Solutions

  1. Map the status code: 403/429 → rate limit or proxy block, 404 → missing asset, 5xx → upstream incident; retry later for 429/5xx.
  2. For GitHub API rate limits, wait for the quota window or supply a token-bearing endpoint where supported.
  3. Verify the exact URL with curl -I to see headers (x-ratelimit-remaining on api.github.com).
  4. If a proxy returns 403, bypass it for the release host or authenticate to it.

Example fix

// before
if resp.StatusCode != http.StatusOK {
    return []byte{}, fmt.Errorf("error: received status code %d", resp.StatusCode)
}

// after: include the URL and a body snippet to make diagnosis immediate
if resp.StatusCode != http.StatusOK {
    snippet, _ := io.ReadAll(io.LimitReader(resp.Body, 200))
    return nil, fmt.Errorf("error: GET %s returned status %d: %s", req.URL, resp.StatusCode, snippet)
}
Defensive patterns

Strategy: retry

Validate before calling

// Check reachability and rate-limit headroom before the request
resp, err := http.Head(url)
if err == nil {
    if remain := resp.Header.Get("X-RateLimit-Remaining"); remain == "0" {
        return fmt.Errorf("rate limited; retry after " + resp.Header.Get("X-RateLimit-Reset"))
    }
}

Try / catch

Switch on the numeric code: 429/5xx → backoff retry with honor for Retry-After; 403 → proxy/auth investigation; 404 → permanent, do not retry, surface the URL.

Prevention

When it happens

Trigger: GitHub API rate limiting (429/403) when the update-check URL hits api.github.com too often from one IP; 404 when a release asset or checksum file is missing; 403 from a proxy or region-blocked CDN; 5xx during GitHub incidents; redirect chains ending somewhere non-200.

Common situations: CI machines sharing an egress IP exhausting the unauthenticated GitHub API quota; release asset renamed by maintainers; corporate proxies returning 403 challenge pages; users in regions where GitHub serves intermittently.

Related errors


AI-assisted analysis of coreybutler/nvm-windows@5b18223ca1 (2026-08-15). Data as JSON: /api/errors/871132e1b6362041. Report an issue: GitHub.