Fix Claude Code Action 403 permission errors
When Claude Code Action fails with 403 Resource not accessible by integration, check the token type, permissions block, repo defaults, then fork PRs.
A workflow triggered by an @claude comment or a prompt ended with 403 Resource not accessible by integration. Work out which token made the request and what permissions it had.
[1] Look at the uses: anthropics/claude-code-action@v1 step and check whether it has a github_token input. Without one, the action authenticates as the Claude GitHub App. With one, it uses that token. What to inspect depends on which case you are in.
github_token | Who sends the request | Check first |
|---|---|---|
| none | Claude GitHub App | app installed · id-token: write · app permissions |
secrets.GITHUB_TOKEN | the workflow token | permissions: block · repository default permissions |
| a token from your own app | that app | the app's Contents, Issues, Pull requests |
[2] Compare your permissions: block with the official example. If you set any permission, GitHub sets every one you left out to none, so a block holding only contents: read removes all write access. The official example for answering @claude:
jobs: claude: runs-on: ubuntu-latest permissions: contents: write pull-requests: write issues: write id-token: write actions: readid-token: write is required for the default authentication (the Claude GitHub App). Without it you hit the OIDC authentication error in the action's FAQ. actions: read lets Claude read CI results on a PR; drop it if you don't need that.
[3] Pick write permissions that match the job. The docs give these purposes for the app permissions:
| Permission | Purpose in the docs |
|---|---|
| Contents: read and write | modify repository files · create branches |
| Pull requests: read and write | create PRs and push changes |
| Issues: read and write | respond to issues · update comments |
The docs' code-review example sets contents, pull-requests and issues to read and raises only id-token: write, yet it posts the review on the PR with --comment. The @claude example that edits files and pushes sets all three to write. If a workflow only needs to comment, start with read and raise it when pushing becomes necessary.
[4] Open the repository's Settings → Actions → General → Workflow permissions. The choices are read and write access for all permissions, or read-only access for contents and packages. If the repository belongs to an organization that picked a more restrictive default, the same option is selected in the repository and the permissive one is disabled. Ask an organization owner to change it.
[5] Catch typos with actionlint. This is 1.7.12 run on a file where pull-requests was misspelled pull-request:
$ actionlint typo.ymltypo.yml:13:7: unknown permission scope "pull-request". all available permission scopes are "actions", "artifact-metadata", "attestations", "checks", "contents", "deployments", "discussions", "id-token", "issues", "models", "packages", "pages", "pull-requests", "repository-projects", "security-events", "statuses" [permissions] |13 | pull-request: write | ^~~~~~~~~~~~~It also rejects values a scope doesn't accept, such as id-token: read:
$ actionlint badvalue.ymlbadvalue.yml:15:17: "read" is invalid as permission of scope "id-token". available values are "write", "none" [permissions][6] If the 403 persists, go by situation.
- PR from a fork: for workflows run by a fork PR (not
pull_request_target), write permissions are lowered to read-only unless Send write tokens to workflows from pull requests is enabled. On public repositories GitHub also withholds secrets from fork PR runs. - **Automation mode with
prompt**: the FAQ describes a 403 caused by the action calling/userwith an app token. The action now uses defaultbot_idandbot_name, so make sure you are on@v1; for a custom bot, set both inputs. - Asking Claude to edit workflow files: the FAQ says the Claude GitHub App has no workflow write access. Edit anything under
.github/workflows/yourself. - Who commented: on issue and PR events the triggering user needs write access to the repository.
- App not installed: confirm the Claude GitHub App is installed on that repository.