hashicorp/packer · error

HTTP request failed: %w

Error message

HTTP request failed: %w

What it means

After building the GET request for the release artifact, downloadURLToTempFile performs client.Do(req) to download the zip from releases.hashicorp.com. If the HTTP exchange itself fails — before any status code is even available — the temp file is closed and removed and this error is returned with the underlying net/http error wrapped. It indicates a transport-level problem: DNS, TCP, TLS, timeout, or cancelled context, not an HTTP error status (a non-200 yields 'HTTP %d for %s' instead).

Source

Thrown at provisioner/hcp-sbom/packer_release_fetch.go:120

func downloadURLToTempFile(ctx context.Context, client *http.Client, url, suffix string) (string, error) {
	f, err := os.CreateTemp("", "packer-dl-*"+suffix)
	if err != nil {
		return "", fmt.Errorf("failed to create temp file: %w", err)
	}
	tmpPath := f.Name()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		_ = f.Close()
		_ = os.Remove(tmpPath)
		return "", err
	}

	resp, err := client.Do(req)
	if err != nil {
		_ = f.Close()
		_ = os.Remove(tmpPath)
		return "", fmt.Errorf("HTTP request failed: %w", err)
	}
	defer func() { _ = resp.Body.Close() }()

	if resp.StatusCode != http.StatusOK {
		_ = f.Close()
		_ = os.Remove(tmpPath)
		return "", fmt.Errorf("HTTP %d for %s", resp.StatusCode, url)
	}

	_, copyErr := io.Copy(f, resp.Body)
	closeErr := f.Close()
	if copyErr != nil {
		_ = os.Remove(tmpPath)
		return "", fmt.Errorf("failed to write download: %w", copyErr)
	}
	if closeErr != nil {
		_ = os.Remove(tmpPath)
		return "", fmt.Errorf("failed to close temp file: %w", closeErr)

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Read the wrapped cause in the message and verify basic reachability: curl -v https://releases.hashicorp.com/packer/ from the build machine.
  2. Check DNS on the machine (nslookup releases.hashicorp.com) and fix resolver config if it fails.
  3. If behind a corporate proxy, set HTTPS_PROXY/HTTP_PROXY for the process or configure the http.Client Transport's Proxy.
  4. Retry the build — downloadPackerRelease already retries 3 times with 5s delay, so persistent failure means the network path, not transience, is broken.
  5. Check firewall/egress rules to allow HTTPS (443) to releases.hashicorp.com, and confirm the context isn't being cancelled by an outer timeout that is too short.

Example fix

// before: fail hard when the download cannot reach the network
path, err := downloadURLToTempFile(ctx, client, zipURL, ".zip")
// after: surface and handle transient network errors with your own bounded retry
var path string
err = retry.Config{Tries: 5, RetryDelay: func() time.Duration { return 10 * time.Second }}.
    Run(ctx, func(ctx context.Context) error {
        p, err := downloadURLToTempFile(ctx, client, zipURL, ".zip")
        if err != nil && isRetryableNetErr(err) { return err }
        if err != nil { return retry.Fatal(err) }
        path = p
        return nil
    })
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight reachability check before starting the download flow
func reachable(endpoint string) error {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    req, _ := http.NewRequestWithContext(ctx, http.MethodHead, endpoint, nil)
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return fmt.Errorf("releases host unreachable: %w", err)
    }
    resp.Body.Close()
    return nil
}

Try / catch

var path string
err := retry.Config{
    Tries:      4,
    RetryDelay: func() time.Duration { return 10 * time.Second },
}.Run(ctx, func(ctx context.Context) error {
    p, err := downloadURLToTempFile(ctx, client, url, ".zip")
    if err == nil {
        path = p
        return nil
    }
    if strings.HasPrefix(err.Error(), "HTTP ") {
        return retry.Fatal(err) // server responded: status errors are not transient
    }
    return err // transport error: safe to retry
})
if err != nil {
    return fmt.Errorf("download failed after retries: %w", err)
}

Prevention

When it happens

Trigger: client.Do returns an error: DNS resolution failure for releases.hashicorp.com, connection refused/timeout, TLS handshake/certificate errors, the 5-minute client timeout elapses mid-transfer, the context is cancelled, or a proxy is unreachable.

Common situations: Build agents without internet access or behind a corporate proxy that requires configuration; DNS misconfiguration; transient network flaps between retries; firewall or egress rules blocking releases.hashicorp.com; slow links exceeding the 5-minute HTTP client timeout while downloading large zips.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/4a6c1a42e6eac35b. Report an issue: GitHub.