GitHub Actions "Resource not accessible" Setting a Commit Status
A step that sets a commit status (a custom context shown on the commit and PR) fails with a 403 because the workflow token lacks statuses: write.
What this error means
A call to create a commit status returns "Resource not accessible by integration", so the custom status context never appears on the commit or pull request.
Error: Resource not accessible by integration
status: 403
POST /repos/org/repo/statuses/{sha}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.
- 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 }}Common causes
Missing statuses: write permission
Creating commit statuses requires statuses: write. It is not granted under restricted default permissions, so the call is denied.
Confusing statuses with checks
The Statuses API and the Checks API are different. Granting checks: write does not enable the statuses endpoint, and vice versa.
How to fix it
Grant statuses: write
permissions:
contents: read
statuses: write
jobs:
report:
runs-on: ubuntu-latestGrant the right scope for the API you use
- Use statuses: write for the commit Statuses API.
- Use checks: write for the Checks API (check runs and annotations).
- Scope the permission to the job that writes the status.
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.
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 runsHow to prevent it
- Match the permission scope to the exact API the step calls.
- Grant statuses: write only on the reporting job.
- Keep default workflow permissions read-only and opt in per job.