hashicorp/packer · error
request GitHub OIDC token: unexpected status %s
Error message
request GitHub OIDC token: unexpected status %s
What it means
GitHub's OIDC token endpoint responded, but with a non-2xx status code. The full HTTP status string (e.g. "403 Forbidden", "401 Unauthorized") is embedded in the error. This means the audience-augmented token request was rejected by the server, typically due to authentication or permissions.
Source
Thrown at internal/attestation/sign_keyless.go:350
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 {
return "", fmt.Errorf("decode GitHub OIDC token response: %w", err)
}
return strings.TrimSpace(payload.Value), nil
}
View on GitHub (pinned to eb36e3c3e4)
Solutions
- Read the embedded status: 403/404 usually means missing `permissions: id-token: write`; 401 means the request token is invalid or expired.
- Add `permissions: id-token: write` to the workflow/job in GitHub Actions.
- Ensure the token request happens within the same job run that issued ACTIONS_ID_TOKEN_REQUEST_TOKEN.
- Confirm the repository/organization OIDC policy allows token issuance.
- Bypass the endpoint by supplying SIGSTORE_ID_TOKEN directly.
Example fix
// before (workflow)
jobs:
sign:
steps:
- uses: actions/checkout@v4
// after
jobs:
sign:
permissions:
id-token: write # also add contents: read if needed
contents: read
steps:
- uses: actions/checkout@v4 Defensive patterns
Strategy: type-guard
Validate before calling
// inspect the status embedded in the error and branch
switch {
case strings.Contains(err.Error(), "403"), strings.Contains(err.Error(), "404"):
return fmt.Errorf("workflow lacks id-token: write permission")
case strings.Contains(err.Error(), "401"):
return fmt.Errorf("OIDC request token invalid or expired")
} Type guard
func isOIDCPermissionError(err error) bool {
return err != nil && (strings.Contains(err.Error(), "403") || strings.Contains(err.Error(), "404")) &&
strings.Contains(err.Error(), "unexpected status")
}
func isOIDCAuthError(err error) bool {
return err != nil && strings.Contains(err.Error(), "401") && strings.Contains(err.Error(), "unexpected status")
} Try / catch
signer, err := newKeylessSigner(ctx, cfg)
if err != nil && strings.Contains(err.Error(), "unexpected status") {
if isOIDCPermissionError(err) {
return fmt.Errorf("add `permissions: id-token: write` to the workflow")
}
return fmt.Errorf("GitHub OIDC endpoint rejected the token request: %w", err)
} Prevention
- Always set `permissions: id-token: write` on signing workflows.
- Request the OIDC token within the same job that signs — request tokens are short-lived.
- Check organization/repository OIDC policies before enabling keyless signing.
- Keep SIGSTORE_ID_TOKEN as a fallback path for environments where OIDC is disabled.
When it happens
Trigger: resolveGitHubActionerIDToken receives a response whose StatusCode/100 != 2: the ACTIONS_ID_TOKEN_REQUEST_TOKEN is expired/invalid, the workflow lacks id-token: write permission, the repository/organization restricts OIDC, or the custom endpoint (proxy/mock) returns an error status.
Common situations: GitHub Actions job without `permissions: id-token: write` (403/404); reusing an OIDC request token from a different job after it expired (401); enterprise policy disabling OIDC for the repo; pointing ACTIONS_ID_TOKEN_REQUEST_URL at a stub server returning 500.
Related errors
- create GitHub OIDC request: %w
- request GitHub OIDC token: %w
- parse GitHub OIDC request URL: %w
- decode GitHub OIDC token response: %w
- signing_mode %q requires an ambient OIDC token; set SIGSTORE
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/82021c528d22c31f.
Report an issue: GitHub.