hashicorp/packer · error

failed to build request for %s: %w

Error message

failed to build request for %s: %w

What it means

downloadChecksumFile builds an http.Request via http.NewRequestWithContext before fetching the SHA256SUMS file. This error wraps the parse/validation error returned when the URL string is malformed or cannot be turned into a request (e.g. net/url.Parse failure or unsupported scheme). It fires before any network I/O, so the checksum file was never requested.

Source

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

	_, 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)
	}

	return tmpPath, nil
}

// downloadChecksumFile fetches the SHA256SUMS text file at url.
func downloadChecksumFile(ctx context.Context, client *http.Client, url string) (string, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return "", fmt.Errorf("failed to build request for %s: %w", url, err)
	}

	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("failed to download %s: %w", url, err)
	}
	defer func() { _ = resp.Body.Close() }()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("download failed: HTTP %d for %s", resp.StatusCode, url)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("failed reading response body for %s: %w", url, err)
	}
	if len(strings.TrimSpace(string(body))) == 0 {
		return "", fmt.Errorf("empty response body for %s", url)

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Inspect the URL printed in the error message and correct it — it must be absolute with an http:// or https:// scheme and valid percent-encoding
  2. Verify the release base URL override has no leading/trailing spaces, control characters, or missing scheme
  3. Sanitize/validate the base URL with net/url.Parse before passing it into the download flow
  4. If the URL looks correct, check the version string used in interpolation for embedded whitespace

Example fix

// before
base := "releases.hashicorp.com"            // missing scheme -> parse error
// after
base := "https://releases.hashicorp.com"    // absolute URL with valid scheme
if _, err := url.Parse(base); err != nil {
    log.Fatalf("invalid release base URL: %v", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// validate the release base URL before it reaches downloadChecksumFile
u, err := url.Parse(base)
if err != nil {
    return fmt.Errorf("invalid release base URL %q: %w", base, err)
}
if u.Scheme != "http" && u.Scheme != "https" {
    return fmt.Errorf("release base URL %q must use http or https", base)
}
if u.Host == "" {
    return fmt.Errorf("release base URL %q has no host", base)
}

Type guard

func isValidHTTPURL(s string) bool {
    u, err := url.Parse(s)
    return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}

Try / catch

// unwrap and classify the cause for clear diagnostics
_, err := downloadChecksumFile(ctx, client, shaSumsURL)
if err != nil {
    var ue *url.Error
    if errors.As(err, &ue) && ue.Op == "parse" {
        return fmt.Errorf("malformed checksum URL: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: http.NewRequestWithContext(ctx, http.MethodGet, url, nil) returns err for the SHA256SUMS URL — a URL that fails net/url parsing (control characters, invalid percent-encoding, spaces) or a scheme other than http/https. In this code path the URL is built as base + "/packer/" + v + "/packer_" + v + "_SHA256SUMS", so only a corrupt base URL produces it in normal operation.

Common situations: A custom/test release base URL containing invalid characters or missing a scheme (e.g. "releases.hashicorp.com" instead of "https://releases.hashicorp.com"); interpolation injecting whitespace or newline into the URL; typos when overriding defaultReleaseBaseURL in modified builds.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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