pnpm/pnpm · error · IdTokenGitHubInvalidResponseError
ID_TOKEN_GITHUB_INVALID_RESPONSE
ID_TOKEN_GITHUB_INVALID_RESPONSE
Error message
Failed to fetch idToken from GitHub: received an invalid response
What it means
The GET to GitHub's OIDC token endpoint ($ACTIONS_ID_TOKEN_REQUEST_URL with audience=npm:<registry-host>) completed with a non-ok HTTP status. The log line pnpm prints just before the throw (GET <url> <status> <elapsed>ms) carries the exact status: 400 usually means a malformed request/audience, 403 an expired or invalid request token (the env vars are single-job and go stale when reused).
Source
Thrown at pnpm11/releasing/commands/src/publish/oidc/idToken.ts:126
headers: {
Accept: 'application/json',
Authorization: `Bearer ${env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}`,
},
method: 'GET',
retry: {
factor: options?.fetchRetryFactor,
maxTimeout: options?.fetchRetryMaxtimeout,
minTimeout: options?.fetchRetryMintimeout,
retries: options?.fetchRetries,
},
timeout: options?.fetchTimeout,
})
const elapsedTime = Date.now() - startTime
globalInfo(`GET ${url.href} ${response.status} ${elapsedTime}ms`)
if (!response.ok) {
throw new IdTokenGitHubInvalidResponseError()
}
let json: unknown
try {
json = await response.json()
} catch (error) {
throw new IdTokenGitHubJsonInterruptedError(error)
}
if (!json || typeof json !== 'object' || !('value' in json) || typeof json.value !== 'string') {
throw new IdTokenGitHubJsonInvalidValueError(json)
}
return json.value
}
export abstract class IdTokenError extends PnpmError {}
View on GitHub (pinned to 6261b7f388)
Solutions
- Check the `GET ... <status>` log line printed above the error for the concrete status code
- Re-run the workflow — 5xx responses from the token endpoint are transient
- Run the pnpm publish step in the same job where the OIDC env vars were minted; never pass or cache them across jobs
- If publishing to a custom registry, verify its hostname — the audience is derived from it as npm:<host>
Defensive patterns
Strategy: try-catch
Try / catch
try {
await publish(pkg)
} catch (err) {
if ((err as any).code === 'ID_TOKEN_GITHUB_INVALID_RESPONSE') {
// the `GET <url> <status> <ms>` log line above names the status:
// 403 => stale ACTIONS_ID_TOKEN vars (re-run in-job), 5xx => transient (re-run workflow)
throw err
}
} Prevention
- Never persist or pass ACTIONS_ID_TOKEN_* env vars between jobs — they are minted per job
- Keep the publish step in the same job that checks out and builds, so the OIDC vars are fresh
When it happens
Trigger: The ACTIONS_ID_TOKEN_* env vars were captured in one job and re-used in another (the token is short-lived and job-scoped); a tampered audience query; transient GitHub-side 5xx.
Common situations: Workflows that pass the OIDC env vars between jobs or cache them; rare GitHub outages; manual re-running of a step after the request token expired.
Related errors
- AUTH_TOKEN_EXCHANGE
- ID_TOKEN_GITHUB_WORKFLOW_INCORRECT_PERMISSIONS
- PROVENANCE_INSUFFICIENT_INFORMATION
- failed to parse the idToken payload: {_0}
- ID_TOKEN_GITHUB_JSON_INTERRUPTED_ERROR
AI-assisted analysis of pnpm/pnpm@6261b7f388 (2026-08-17).
Data as JSON: /api/errors/18de0c161b5b76ba.
Report an issue: GitHub.