# GitHub Actions OIDC "Failed to get ID token"

> Fix GitHub Actions OIDC "Failed to get ID token" - a missing id-token permission, an unset request URL, or a transient token-endpoint failure when requesting the workflow OIDC token.

Source: https://latchkey.dev/learn/github-actions/github-actions-oidc-id-token-error  
Updated: 2026-06-26

A step asked GitHub for an OIDC ID token and the request failed. The usual cause is that the job never granted id-token: write (so the token endpoint is unavailable), but it can also be a transient failure of the token endpoint itself.

## Diagnose it: what token do you actually have?

Permission failures in Actions are almost never about your repository settings alone. Three things combine: the default `GITHUB_TOKEN` permission set for the repo or organization, the `permissions:` block in the workflow, and whether the event is a fork pull request, which downgrades the token to read-only regardless of everything else.

```.github/workflows/ci.yml
- name: Show the token scopes actually granted
  run: |
    curl -sI -H "Authorization: Bearer $GITHUB_TOKEN" \
      https://api.github.com/ | grep -i "^x-oauth-scopes\|^x-accepted"
    echo "event: ${{ github.event_name }}"
    echo "fork PR: ${{ github.event.pull_request.head.repo.fork }}"
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

> If `fork PR` prints `true`, stop looking at `permissions:`. A fork pull request gets a read-only token by design, and no workflow-level grant can raise it.

## Grant the narrowest permission that works

Declaring a `permissions:` block switches the job from the repository default to exactly what you list, so an incomplete block is a common cause of a new failure right after someone tightened security. List every scope the job needs, not just the one that failed.

```.github/workflows/ci.yml
permissions:
  contents: read        # checkout
  packages: write       # push to GHCR
  id-token: write       # OIDC to a cloud provider
  pull-requests: write  # comment on or label a PR
  checks: write         # publish check runs
```

> Set `permissions` at the job level rather than the workflow level where you can. A workflow-level grant applies to every job, including ones that only run tests.

## FAQ

### What causes GitHub Actions OIDC "Failed to get ID token"?

There are 3 common causes: missing id-token: write permission, default-permissions or org policy restricts the token, and transient oidc token-endpoint failure. Without permissions: id-token: write on the job (or workflow), GitHub does not expose the OIDC request URL/token to the runner, so any token request fails immediately.

### How do I fix GitHub Actions OIDC "Failed to get ID token"?

There are 3 fixes depending on which cause you have: grant id-token: write on the job, confirm org/enterprise policy allows the id-token scope, and retry a transient token-endpoint failure. Work through them in order, since the first is the most common.

### What does GitHub Actions OIDC "Failed to get ID token" actually mean?

A step that requests an OIDC token (cloud login, attestation, or a custom getIDToken call) fails with "Failed to get ID token" or a related OIDC request error, before any cloud credentials are exchanged.

### How do I stop GitHub Actions OIDC "Failed to get ID token" happening again?

Set permissions: id-token: write explicitly on any job that uses OIDC. The prevention section lists 3 changes that keep it from recurring.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
