hashicorp/packer · error

create GitHub OIDC request: %w

Error message

create GitHub OIDC request: %w

What it means

http.NewRequestWithContext failed to build the GET request to GitHub's OIDC token endpoint. Given that the URL already parsed successfully, this almost always means the constructed URL string (after adding the audience query parameter) is invalid — practically only via an invalid method/URL combination or context-related construction edge cases.

Source

Thrown at internal/attestation/sign_keyless.go:338

	requestURL := strings.TrimSpace(env["ACTIONS_ID_TOKEN_REQUEST_URL"])
	requestToken := strings.TrimSpace(env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"])
	if requestURL == "" || requestToken == "" {
		return "", nil
	}

	parsedURL, err := url.Parse(requestURL)
	if err != nil {
		return "", fmt.Errorf("parse GitHub OIDC request URL: %w", err)
	}
	query := parsedURL.Query()
	if query.Get("audience") == "" {
		query.Set("audience", "sigstore")
		parsedURL.RawQuery = query.Encode()
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, parsedURL.String(), nil)
	if err != nil {
		return "", fmt.Errorf("create GitHub OIDC request: %w", err)
	}
	req.Header.Set("Authorization", "Bearer "+requestToken)

	client := &http.Client{Timeout: 30 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("request GitHub OIDC token: %w", err)
	}
	defer func() { _ = resp.Body.Close() }()

	if resp.StatusCode/100 != 2 {
		return "", fmt.Errorf("request GitHub OIDC token: unexpected status %s", resp.Status)
	}

	var payload struct {
		Value string `json:"value"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Ensure ACTIONS_ID_TOKEN_REQUEST_URL is an absolute URL with scheme and host (https://...).
  2. Compare the URL string before and after audience-parameter augmentation to spot corruption.
  3. Check the wrapped error's URL field for the exact rejected value.
  4. Bypass by exporting SIGSTORE_ID_TOKEN directly if the endpoint override cannot be fixed.

Example fix

// before
env["ACTIONS_ID_TOKEN_REQUEST_URL"] = "localhost:8080/tokens"
// after
env["ACTIONS_ID_TOKEN_REQUEST_URL"] = "http://localhost:8080/tokens"
Defensive patterns

Strategy: validation

Validate before calling

raw := strings.TrimSpace(env["ACTIONS_ID_TOKEN_REQUEST_URL"])
if u, err := url.Parse(raw); err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("ACTIONS_ID_TOKEN_REQUEST_URL must be an absolute URL with scheme and host")
}

Type guard

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

Try / catch

signer, err := newKeylessSigner(ctx, cfg)
if err != nil && strings.Contains(err.Error(), "create GitHub OIDC request") {
    return fmt.Errorf("could not build OIDC token request; check ACTIONS_ID_TOKEN_REQUEST_URL is absolute: %w", err)
}

Prevention

When it happens

Trigger: resolveGitHubActionsIDToken calls http.NewRequestWithContext with the audience-augmented ACTIONS_ID_TOKEN_REQUEST_URL, and Go's request constructor rejects the resulting absolute URL (e.g. a scheme-less URL that only worked for url.Parse).

Common situations: ACTIONS_ID_TOKEN_REQUEST_URL overridden to a relative or scheme-less value like "localhost/token" that url.Parse accepts but the HTTP client's request constructor deems invalid for a request target.

Related errors


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