{"record":{"id":"00d480b7ff0cc0ec","repo":"hashicorp/packer","slug":"failed-to-fetch-s-w","errorCode":null,"errorMessage":"failed to fetch %s: %w","messagePattern":"failed to fetch (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packer/plugin-getter/remote/getter.go","lineNumber":126,"sourceCode":"\t\tout = append(out, plugingetter.Release{Version: \"v\" + v})\n\t}\n\tbuf := &bytes.Buffer{}\n\tif err := json.NewEncoder(buf).Encode(out); err != nil {\n\t\treturn nil, err\n\t}\n\treturn io.NopCloser(buf), nil\n}\n\n// fetchStream returns the response body of url for the caller to consume\n// and close; fetch buffers it, for the small metadata files.\nfunc (g *Getter) fetchStream(url string) (io.ReadCloser, error) {\n\tif g.HttpClient == nil {\n\t\tg.HttpClient = &http.Client{}\n\t}\n\tlog.Printf(\"[DEBUG] remote-getter: getting %q\", url)\n\tresp, err := g.HttpClient.Get(url)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to fetch %s: %w\", url, err)\n\t}\n\tif resp.StatusCode >= 400 {\n\t\t_ = resp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"%s returned status %d\", url, resp.StatusCode)\n\t}\n\treturn resp.Body, nil\n}\n\nfunc (g *Getter) fetch(url string) ([]byte, error) {\n\tbody, err := g.fetchStream(url)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() { _ = body.Close() }()\n\treturn io.ReadAll(body)\n}\n\n// pluginPath returns the URL path of the plugin below the host, e.g.","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/packer/plugin-getter/remote/getter.go#L108-L144","documentation":"fetchStream performs the raw HTTP GET for remote registry streams (index.json, releases list, etc.). Any transport-level failure — DNS failure, connection refused, TLS error, timeout, context cancellation — is wrapped as \"failed to fetch %s: %w\" with the underlying cause preserved.","triggerScenarios":"g.HttpClient.Get(url) returns a non-nil error during Get/fetch — offline machine, unresolvable hostname, blocked egress, TLS interception, or a canceled context.","commonSituations":"No internet access or DNS failure when installing plugins; corporate firewall/proxy blocking releases.hashicorp.com or a custom registry host; expired/misconfigured TLS on a self-hosted registry; transient network flaps.","solutions":["Check network connectivity and DNS resolution for the URL in the error message (curl it).","Configure HTTPS_PROXY/HTTP_PROXY if egress requires a proxy.","Retry if the failure was transient (timeouts, resets).","Fix TLS trust (install the corporate CA) if the error is a certificate error."],"exampleFix":"// before\nexport PACKER_PLUGIN_PATH=...  # behind proxy, fails\n// after\nexport HTTPS_PROXY=http://proxy.corp:3128\npacker plugins install ...","handlingStrategy":"retry","validationCode":"u, err := url.Parse(registryURL)\nif err != nil || u.Host == \"\" {\n    return fmt.Errorf(\"invalid registry host\")\n}\nif _, err := net.LookupHost(u.Hostname()); err != nil {\n    return fmt.Errorf(\"cannot resolve %s; check network/DNS/proxy\", u.Hostname())\n}","typeGuard":null,"tryCatchPattern":"var body io.ReadCloser\nvar err error\nfor i := 0; i < 3; i++ {\n    body, err = g.Get(\"releases\", opts)\n    if err == nil || !isTransientNetErr(err) {\n        break\n    }\n    time.Sleep(time.Duration(1<<i) * time.Second)\n}","preventionTips":["Verify HTTPS_PROXY/NO_PROXY are set in restricted networks.","Precheck DNS/connectivity to the registry host before installs.","Install corporate CA certs when behind TLS inspection.","Retry transient failures with exponential backoff."],"tags":["packer","plugin-getter","network","http-client"],"backgroundTag":"http-request-failed","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}