Repository navigation
--delete-branch fails, if branch is deleted already (race condition) #11187
Description
Activity
Thanks for reporting this, @V0idC0de! 🎉
I couldn't reproduce this, perhaps due to the race-condition nature. However, I checked with the platform, and it seems the error message
Reference does not existcan be returned along with both404or422status codes. The underlying reason is different, but it doesn't make any difference for our use case. Also, it seems this situation (i.e. a404response) is rare.Note
I looked for similar issues in other projects and found a few cases.
- Renovate seems to have had a similar problem (in
GET) and they did a similar fix: - Octokit also faced a similar case (a
GETrequest):
So, I can confirm what you're seeing is an uncovered API behaviour in
gh. I'm going to put down the A/C for this change in the next comment.Further investigation
The interesting part is,
HTTP 422can be returned in a couple of situations, one of which is when the ref is not found. So, I think the current implementation is not quite correct, since it's just based on a mere status code check:Lines 460 to 468 in 5ac1846
if !m.merged { apiClient := api.NewClientFromHTTP(m.httpClient) err := api.BranchDeleteRemote(apiClient, m.baseRepo, m.pr.HeadRefName) var httpErr api.HTTPError // The ref might have already been deleted by GitHub if err != nil && (!errors.As(err, &httpErr) || httpErr.StatusCode != 422) { return fmt.Errorf("failed to delete remote branch %s: %w", m.cs.Cyan(m.pr.HeadRefName), err) } } As with our API errors, detecting the cause of an error (without checking the error message) is not possible. For example, this is the error response we get when an API call to delete a ref fails:
{ "message": "Reference does not exist", "documentation_url": "https://docs.github.com/rest/git/refs#delete-a-reference", "status": "422" }I'm not sure if we're going to introduce another error message check, though.
- Renovate seems to have had a similar problem (in
The A/C here is a bit awkward since the changes is almost invisible from the user's side. However, an A/C feels more appropriate than an E/O.
For now I assumed we're not going to check the error messages. The reasons are:
- Checking error messages is not a future-proof approach.
- An
HTTP 404error is only raised when the ref is not found, so there's no need to check for the message. What has been already done forHTTP 422remains the same and since we haven't received issues or bug reports for it, we can assume it's been working fine.
Acceptance Criteria
Given I have a PR ready to be merged AND the branch is already deleted (delete ref API returns 404)
When I rungh pr merge --delete-branch
Thenghshould exit without an error (zero exit-code)- addedgh-prrelating to the gh pr commandrelating to the gh pr commandpriority-3Affects a small number of users or is largely cosmeticAffects a small number of users or is largely cosmeticand removedneeds-triageneeds to be reviewedneeds to be reviewed
on Jul 4, 2025 - linked a pull request that will close this issueHandle `HTTP 404` when deleting remote branch in `pr merge` #11234
on Jul 5, 2025 @V0idC0de, This is now fixed in our latest release
v2.75.0. However, it takes a couple of weeks for GitHub runners to upgrade their installation. If that's a blocker, you might want to manually upgradeghin your workflow.Reacted by V0idC0de
Describe the bug
When using
gh pr merge --delete-branch, the command sometimes fails, if the branch was deleted already. This is unintuitive, since I want to make sure the branch is cleaned up and don't care how it happens, unless it interferes with the actual command.#1279 already addresses this behavior, but I'm still getting an error.
I wondered, whether this is intentional or not. If intentional, where is the difference to the behavior addressed in the aforementioned PR and how I should go about ensuring the branch is gone after the merge, without risking a pipeline fail.
Affected version
GitHub CLI 2.74.2 (pipeline ran today and was using the Ubuntu 24.04 runner image, thus this is the installed version)
Steps to reproduce the behavior
ghwill error with aHTTP 404Expected vs actual behavior
I'd expect the command to not error, but gracefully handle the error and suppressing it, since it matches the intent.
Currently it fails with
failed to delete remote branch <redacted>: HTTP 404: Reference does not exist (https://api.github.com/repos/<redacted>).#1279 already addresses this issue, but the caught error doesn't include the
HTTP 404I'm observing here.I'd argue, that the command should not raise this error, since my intention is "branch should be cleaned up and gone after merge". If the branch is already gone, that's fine, as far as I'm concerned. The fact, that the branch was deleted by some other actor has no impact on my
gh pr mergecommand, since the merge already happened, thus the command shouldn't care and shouldn't fail, just because it could not delete the branch by itself.Logs
There is only one relevant log line, as
gh pr mergedoesn't output anything else for me.failed to delete remote branch <redacted>: HTTP 404: Reference does not exist (https://api.github.com/repos/<redacted>)