GitHub Actions "Pull request is not mergeable" (auto-merge)
Enabling auto-merge or merging via the API only succeeds when the PR is in a mergeable state. Conflicts, required-but-unfinished checks, or unmet branch protection rules return a not-mergeable error.
What this error means
An auto-merge/merge step fails reporting the pull request is not mergeable, even though the workflow expects to merge it.
Error: Pull request is not mergeable (405).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
Required checks not yet passing
Branch protection requires status checks that have not completed.
Merge conflicts or review requirements
Conflicts or unmet review/approval rules block the merge.
How to fix it
Use auto-merge and satisfy protection
- Enable auto-merge so GitHub merges once all required checks pass.
- Ensure the workflow has the permissions to enable auto-merge.
- Resolve conflicts and satisfy required reviews/approvals.
permissions:
contents: write
pull-requests: write
steps:
- run: gh pr merge "${{ github.event.pull_request.number }}" --auto --squash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}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
- Prefer --auto so merges wait for required checks instead of failing.
- Keep branch protection rules and workflow expectations aligned.