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

  1. Check the `GET ... <status>` log line printed above the error for the concrete status code
  2. Re-run the workflow — 5xx responses from the token endpoint are transient
  3. Run the pnpm publish step in the same job where the OIDC env vars were minted; never pass or cache them across jobs
  4. 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

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


AI-assisted analysis of pnpm/pnpm@6261b7f388 (2026-08-17). Data as JSON: /api/errors/18de0c161b5b76ba. Report an issue: GitHub.