Skip to content
Latchkey LogoLatchkey home

GitHub Actions Pull Request is not mergeable with auto-merge

GitHub Actions Pull Request is not mergeable is GitHub declining a merge call for the state the pull request is in right now, and the same sentence also shows up on the timeline when auto-merge is switched off later. Which of the two you are reading decides whether anything was wrong with your workflow at all.

A merge call refused now, beside auto-merge being withdrawn later on the same timeline
Two different moments. A step error reports the state at the instant of the call; a timeline entry reading "auto-merge was automatically disabled" reports a state that changed after it was armed.

What this error means

A workflow that merges pull requests fails on the merge step, usually not every time. The pull request looks mergeable in the browser by the time anyone checks, and merging it by hand works. Separately, pull requests that had auto-merge enabled sometimes lose it, with a timeline entry carrying the same wording and no failing workflow anywhere. The two are easy to conflate because the sentence is identical.

Actions log, quoted from juliangruber/merge-pull-request-action#4
##[error]Pull Request is not mergeable

Two places the sentence appears

Before changing a workflow, establish which of these you have. They have different causes and only one of them involves your job at all.

Where you found itWhat produced itWhat it says about the pull request
A red step in a workflow runA merge call refused at the moment your job made itIt was not mergeable then, whatever it looks like now
A timeline entry on the pull requestGitHub withdrawing auto-merge after it was enabledIt became unmergeable at some point after auto-merge was armed
A refusal naming a mutation in parenthesesA permission refusal rather than a state oneNothing, because the call never reached the merge logic

Common causes

The workflow merged before mergeability had been computed

The common cause of the intermittent step error. A job that creates or updates a pull request and merges it in the same run frequently arrives before the answer exists. The failure moves between runs because it depends on how quickly the computation finished.

Required checks or reviews are not satisfied yet

Branch protection makes a pull request unmergeable until its conditions are met, and a workflow that merges as soon as its own job finishes has no reason to believe the other required checks are done. The pull request becomes mergeable minutes later, which is why it looks fine afterwards.

The base branch moved and created a conflict

The usual cause of the timeline version. A pull request that was mergeable when auto-merge was armed stops being so when something else lands on the base branch, and GitHub withdraws auto-merge rather than keeping a promise it can no longer keep.

The pull request is a draft or already closed

Worth ruling out quickly, because it produces a refusal that never clears. Neither state is mergeable, and a workflow that iterates over open pull requests can pick up a draft without meaning to.

How to fix it

Decide which version you have before editing anything

  1. If the sentence is in a workflow log, it is a refused call and the timing is the first suspect.
  2. If it is on the pull request timeline beside auto-merge being disabled, no workflow failed and the base branch is the first suspect.
  3. If a mutation name appears in parentheses, it is a permission problem and belongs to a different repair entirely.

Enable auto-merge instead of merging directly

Let GitHub wait for the conditions rather than asking your job to guess when they are met. This removes the race outright and is the right shape for almost every release workflow.

.github/workflows/automerge.yml (illustrative)
      - run: gh pr merge "$NUMBER" --auto --squash
        env:
          GH_TOKEN: ${{ github.token }}
          NUMBER: ${{ github.event.pull_request.number }}

Wait for a definite answer if you must merge directly

Poll the pull request until its mergeability is no longer unknown, then act on the result. Treat an unknown state as "ask again", not as "not mergeable", which is the mistake most hand-rolled merge steps make.

Re-arm auto-merge after resolving a conflict

Auto-merge is not restored automatically once it has been withdrawn. After the conflict is resolved the pull request sits there mergeable and unmerged, which looks like the automation failing silently. Enabling it again is the whole repair.

Mergeability is computed after you ask

GitHub does not keep a merge result standing by. When something asks whether a pull request can be merged, a background computation runs, and until it finishes the state is unknown. A workflow that opens or updates a pull request and immediately tries to merge it is racing that computation, and an unknown state is not a mergeable one.

This explains the most confusing property of the step-error version: it clears on a rerun, and it clears when a human looks, because both of those happen later. The pull request is not being fixed in between. It is simply being asked a second time, after the answer exists.

Why auto-merge is the better instrument

A direct merge call asks "merge this now" and fails whenever the answer is no. Auto-merge asks "merge this when you can", which is what a release workflow usually means. Once enabled, GitHub waits for required checks and required reviews and merges without another run, so there is no race to lose.

The cost is the timeline case on this page. Auto-merge is withdrawn if the pull request becomes unmergeable, most often because the base branch moved and produced a conflict, and the entry is easy to miss. Treat that as a notification rather than as a failure, and re-arm it after resolving the conflict.

Why there is no recorded run on this page

Both versions depend on a pull request that exists on a specific repository at a specific moment, with its own branch protection, its own required checks and its own base branch history. We could open one on our own repository, but every condition that decides the outcome would be ours: our required reviewers, our checks, our merge queue setting. The race in particular is a timing property of GitHub's own background computation, which we can describe but cannot schedule. The line above is quoted from an issue against a merge action.

How to prevent it

  • Prefer auto-merge over a direct merge call in any workflow that does not control when the checks finish.
  • Never treat an unknown mergeability as a negative answer.
  • Watch for the timeline entry on repositories that rely on auto-merge, since nothing fails when it is withdrawn.
  • Exclude drafts explicitly when a workflow iterates over open pull requests.

Frequently asked questions

Why does it pass when I rerun the job?
Because the second attempt happens later. Mergeability is computed in the background when something asks, so a job that merges immediately after creating or updating a pull request can arrive before the result exists. A rerun asks again once the answer is there, without anything about the pull request having changed.
What does "auto-merge was automatically disabled" mean?
That GitHub withdrew a promise it could no longer keep. Auto-merge waits for the pull request to become mergeable, and if the pull request becomes unmergeable instead, usually because the base branch moved and produced a conflict, it is switched off and the timeline records it with this wording. No workflow failed.
Is a mutation name in parentheses the same error?
No. That form is a permission refusal, identifying which GraphQL mutation was declined, and it means the credential lacks the permission the operation requires. The pull request state is irrelevant to it, so rebasing or waiting will not help.
Does enabling auto-merge require anything of the repository?
It has to be allowed in the repository settings before anything can enable it, and the caller needs the permission to do so. If the setting is off, attempts to enable it fail for that reason rather than for the pull request state, which is another case where reading the exact wording saves time.

Related guides

References

Auto-merge waits on your slowest required check. Latchkey starts those jobs instead of queueing them. Start free → 30-day trial · No credit card