coreybutler/nvm-windows · error
error: parsing release: %v
Error message
error: parsing release: %v
What it means
checkForUpdate unmarshals the fetched release JSON into a Release struct. This error means json.Unmarshal failed: the body is not valid JSON or does not match expectations (wrong types, HTML error page parsed as JSON). Classic causes are a proxy returning an HTML block page with 200, a mirror serving a different schema, or the URL pointing at an HTML page instead of the API JSON.
Source
Thrown at src/upgrade/upgrade.go:749
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))
err = json.Unmarshal(body, &r)
if err != nil {
return &u, fmt.Errorf("error: parsing release: %v", err)
}
u.Version = r.Version
utility.DebugLogf("latest version: %s", u.Version)
// Comment the next line when development is complete
// u.Version = "2.0.0"
for _, asset := range r.Assets {
if value, exists := asset["name"]; exists && value.(string) == "update.exe" {
u.Assets = append(u.Assets, value.(string))
}
if value, exists := asset["name"]; exists && value.(string) == "nvm-noinstall.zip" {
u.SourceURL = asset["browser_download_url"].(string)
}
}
utility.DebugLogf("source URL: %s", u.SourceURL)
utility.DebugLogf("assets: %v", u.Assets)View on GitHub (pinned to 5b18223ca1)
Solutions
- Fetch the update URL manually and pipe to a JSON validator to see the actual payload.
- If a proxy injects HTML, bypass it or authenticate; the body seen in the debug log (DebugLogf 'Received:') shows exactly what came back.
- Point the update-check URL back at the official GitHub API JSON endpoint.
- Upgrade nvm-windows manually to a version matching the current feed format.
Defensive patterns
Strategy: validation
Validate before calling
// Sanity-check the payload before unmarshal
trimmed := bytes.TrimSpace(body)
if len(trimmed) == 0 || trimmed[0] != '{' {
return &u, fmt.Errorf("update feed returned non-JSON (likely proxy/captive portal), first byte %q", trimmed[0])
} Try / catch
Catch, log the raw body prefix (already done via DebugLogf 'Received:'), and skip the update — never fall back to guessing a version. Distinguish proxy-HTML responses from schema drift in the message.
Prevention
- Validate content is JSON before unmarshal.
- Avoid third-party mirrors that rewrite the feed format.
- Pin nvm-windows to a version whose feed schema matches.
When it happens
Trigger: Captive portal / proxy returning HTML with status 200; update URL misconfigured to a releases web page instead of the JSON API endpoint; a mirror rewriting the response; truncated body from a flaky connection; upstream schema change where a field changes type and the strict struct rejects it.
Common situations: Hotel/airport captive portals intercepting the update check; NVM update URL overridden to a third-party mirror with a different feed format; GitHub incident serving error pages; new release format after an nvm-windows version change.
Related errors
- error: reading response body: %v
- failed to download v%v arm 64-bit executable
- Failed to extract npm: %v
- Could not download npm for node v%s. Please visit %s to down
- Invalid character(s) found in patch number %q
AI-assisted analysis of coreybutler/nvm-windows@5b18223ca1 (2026-08-15).
Data as JSON: /api/errors/877c3dc54a603d7c.
Report an issue: GitHub.