GitHub Actions "HttpError: Bad credentials" (401) Calling the API
The GitHub API rejected the request with 401 Bad credentials, meaning the token presented is invalid - expired, revoked, empty, or malformed in the Authorization header.
What this error means
A script or action calling the API fails with "HttpError: Bad credentials" and status 401. Unlike a 403, this is about the token being invalid, not lacking a specific permission.
HttpError: Bad credentials
status: 401
at /node_modules/@octokit/request/dist-node/index.jsCommon causes
Expired or revoked token
A PAT that expired or was revoked, or a GITHUB_TOKEN used after the job ended, is no longer valid and returns 401.
Empty or malformed Authorization header
An empty secret, an extra space, or the wrong prefix (e.g. token vs Bearer) makes the header invalid so the API reads it as bad credentials.
How to fix it
Use a valid, current token
Pass a non-expired token and the correct header format (the gh CLI and Octokit handle this for you).
- run: gh api /repos/${{ github.repository }}/issues
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}Check token validity and format
- Confirm the secret is set and not empty (an unset secret yields an empty token).
- Rotate an expired or revoked PAT and update the secret.
- When setting the header manually, use Authorization: Bearer <token> with no stray whitespace.
How to prevent it
- Prefer GITHUB_TOKEN or short-lived App tokens over long-lived PATs.
- Rotate PATs before expiry and keep secrets current.
- Let the gh CLI/Octokit build the Authorization header.