Description
When the calling user has ruleset bypass authority that would resolve a mergeStateStatus: BLOCKED PR (e.g., via bypass_actors with bypass_mode: pull_request matching the user's RepositoryRole), gh pr merge refuses at pre-flight rather than attempting the merge. The error offers --admin
or --auto as escape hatches, neither of which fits what the user actually needs.
The underlying REST API merge endpoint (PUT /repos/{owner}/{repo}/pulls/{n}/merge) does engage bypass correctly when called directly. So the gap
is in gh pr merge's pre-flight logic, not in the API.
For repositories using rulesets with bypass_actors as a deliberate design choice — codifying who can self-merge per design intent rather than via
admin override — this means every PR by a bypass-eligible user falls back to --admin. Bypass becomes configured-but-unused; admin overrides
accumulate as if the rule were misconfigured.
Reproduction
-
Configure a ruleset on main with required_approving_review_count: 1 and:
"bypass_actors": [
{
"actor_id": 5,
"actor_type": "RepositoryRole",
"bypass_mode": "pull_request"
}
]
-
As the bypass-eligible user (here, a repo admin — RepositoryRole=5), open a PR. The PR will have:
- mergeStateStatus: BLOCKED
- reviewDecision: REVIEW_REQUIRED
- reviewCount: 0
-
Confirm bypass eligibility — GET /repos/{owner}/{repo}/rulesets/{id} returns:
"current_user_can_bypass": "pull_requests_only"
4. Try gh pr merge:
$ gh pr merge <PR#> --squash --delete-branch
X Pull request /#<PR#> is not mergeable: the base branch policy prohibits the merge.
To have the pull request merged after all the requirements have been met, add the --auto flag.
To use administrator privileges to immediately merge the pull request, add the --admin flag.
5. Call the REST merge endpoint directly — succeeds, bypass engages:
$ gh api repos///pulls/<PR#>/merge -X PUT -f merge_method=squash
{"sha":"...","merged":true,"message":"Pull Request successfully merged"}
Expected behavior
gh pr merge should detect bypass eligibility before refusing. Two reasonable fix shapes:
- Conservative: if mergeStateStatus: BLOCKED but current_user_can_bypass indicates bypass-via-pull_request, attempt the merge — the API will engage
bypass automatically.
- Simpler: always attempt the API merge and let GitHub's response be authoritative. Bypass engages or it doesn't, and either way the API's response is
meaningful (success, or a real error worth surfacing). The current pre-flight refusal pre-empts an outcome the API would have produced correctly.
Actual behavior
gh pr merge refuses based purely on mergeStateStatus: BLOCKED without checking bypass authority. Suggested escape hatches:
- --admin works but is structurally the wrong fit — admin override loudly overrides a rule that the user is in fact authorized to bypass per design.
- --auto doesn't engage bypass either; auto-merge waits for the original blockers to resolve, which (with bypass authority) won't happen organically.
gh version
gh version 2.90.0 (2026-04-16)
Why this matters
Rulesets with bypass_actors are a natural way to encode "who can self-merge" per design intent for repos with mixed-author models (e.g., bot-authored
PRs requiring review; human-authored PRs not). When gh pr merge doesn't respect bypass, the design becomes ceremony that doesn't deliver: operators
fall back to --admin per PR, repeated admin override erodes the rule's authority, and the codified bypass goes unused.
Current workaround: shell wrapper around gh api .../pulls/{n}/merge -X PUT. Functional but loses the ergonomic value of gh pr merge (mergeStateStatus
visibility, branch deletion semantics, default merge method from repo settings, etc.).
Upstream context
- GitHub Rulesets REST API: https://docs.github.com/en/rest/repos/rules
- current_user_can_bypass field: returned on GET /repos/{owner}/{repo}/rulesets/{id} — could serve as the pre-flight signal gh pr merge is currently
missing
EOF
Description
When the calling user has ruleset bypass authority that would resolve a
mergeStateStatus: BLOCKEDPR (e.g., viabypass_actorswithbypass_mode: pull_requestmatching the user'sRepositoryRole),gh pr mergerefuses at pre-flight rather than attempting the merge. The error offers--adminor
--autoas escape hatches, neither of which fits what the user actually needs.The underlying REST API merge endpoint (
PUT /repos/{owner}/{repo}/pulls/{n}/merge) does engage bypass correctly when called directly. So the gapis in
gh pr merge's pre-flight logic, not in the API.For repositories using rulesets with
bypass_actorsas a deliberate design choice — codifying who can self-merge per design intent rather than viaadmin override — this means every PR by a bypass-eligible user falls back to
--admin. Bypass becomes configured-but-unused; admin overridesaccumulate as if the rule were misconfigured.
Reproduction
Configure a ruleset on
mainwithrequired_approving_review_count: 1and:As the bypass-eligible user (here, a repo admin — RepositoryRole=5), open a PR. The PR will have:
- mergeStateStatus: BLOCKED
- reviewDecision: REVIEW_REQUIRED
- reviewCount: 0
Confirm bypass eligibility — GET /repos/{owner}/{repo}/rulesets/{id} returns:
"current_user_can_bypass": "pull_requests_only"
4. Try gh pr merge:
$ gh pr merge <PR#> --squash --delete-branch
X Pull request /#<PR#> is not mergeable: the base branch policy prohibits the merge.
To have the pull request merged after all the requirements have been met, add the
--autoflag.To use administrator privileges to immediately merge the pull request, add the
--adminflag.5. Call the REST merge endpoint directly — succeeds, bypass engages:
$ gh api repos///pulls/<PR#>/merge -X PUT -f merge_method=squash
{"sha":"...","merged":true,"message":"Pull Request successfully merged"}
Expected behavior
gh pr merge should detect bypass eligibility before refusing. Two reasonable fix shapes:
bypass automatically.
meaningful (success, or a real error worth surfacing). The current pre-flight refusal pre-empts an outcome the API would have produced correctly.
Actual behavior
gh pr merge refuses based purely on mergeStateStatus: BLOCKED without checking bypass authority. Suggested escape hatches:
gh version
gh version 2.90.0 (2026-04-16)
Why this matters
Rulesets with bypass_actors are a natural way to encode "who can self-merge" per design intent for repos with mixed-author models (e.g., bot-authored
PRs requiring review; human-authored PRs not). When gh pr merge doesn't respect bypass, the design becomes ceremony that doesn't deliver: operators
fall back to --admin per PR, repeated admin override erodes the rule's authority, and the codified bypass goes unused.
Current workaround: shell wrapper around gh api .../pulls/{n}/merge -X PUT. Functional but loses the ergonomic value of gh pr merge (mergeStateStatus
visibility, branch deletion semantics, default merge method from repo settings, etc.).
Upstream context
missing
EOF