JR DevTools logoJR DevTools

TF401192: “The source branch has been modified since the last merge attempt” (fix)

You try to complete a pull request in Azure DevOps and get Operation failed: TF401192: The source branch has been modified since the last merge attempt. (409). It looks alarming, but nothing is broken: the pull request changed while you were completing it. Here is what the error means and how to get past it in the browser, in VS Code, with the Azure CLI or with the REST API.

What TF401192 means

Before a pull request can be completed, Azure DevOps makes a test merge of the source branch into the target branch. That merge is based on one specific commit of the source branch, the last merge source commit. When you complete the pull request, your browser or tool tells Azure DevOps which commit it expects. If the source branch has a newer commit by then, Azure DevOps refuses with 409 Conflict and TF401192, so it never completes a merge you haven't seen.

Common reasons the source branch moved on:

New merge shows conflicts? Merge Conflict Resolver resolves them inside the pull request, in the browser, and commits the result to the source branch. Free plan, 14-day Pro trial, no account needed.
Install from the Marketplace See how it works

Fix it in the browser

  1. Reload the pull request page.
  2. Wait until Checking for merge conflicts is gone and the merge has succeeded. If it never finishes, see pull request stuck on “Checking for merge conflicts”.
  3. Look at the new commits on the Commits tab, so you know what you are about to merge.
  4. Choose Complete again. If the button now says Set auto-complete, the new push reset a policy (for example approvals or build validation); see can't complete a pull request after resolving conflicts.

If the new merge has conflicts, resolve them first: see how to resolve merge conflicts in an Azure DevOps pull request.

Fix it in VS Code or another tool

Extensions and tools that complete pull requests for you use the same check. Refresh the pull request in the tool (or close and reopen it) so it picks up the latest source commit, wait for the merge to finish, and complete it again. If the tool keeps failing, complete the pull request once in the browser.

Fix it in a script or the REST API

Completing a pull request through the REST API is a PATCH on the pull request with the status and the source commit you expect:

PATCH https://dev.azure.com/{org}/{project}/_apis/git/repositories/{repo}/pullrequests/{id}?api-version=7.1

{
  "status": "completed",
  "lastMergeSourceCommit": { "commitId": "<current lastMergeSourceCommit.commitId>" }
}

TF401192 means the commitId you sent is no longer the latest. Read the pull request again with a GET, wait until mergeStatus is succeeded, and send the new lastMergeSourceCommit.commitId. In a script, do this in a loop with a short delay and a maximum number of tries, so a pipeline that pushes once doesn't fail your run. The same applies to az repos pr update --status completed: run it again once the merge has finished.

It keeps happening

Then something keeps pushing to the source branch. Check the branch's Pushes (Repos → Pushes) or the pull request's Commits tab for who or what pushed last. Usually it is a pipeline that commits during build validation. Let that pipeline push only after the pull request is merged, or set Set auto-complete on the pull request: Azure DevOps then completes it itself once the latest merge and all policies have passed, so you don't race the pushes.

Resolve conflicts without a local clone: Merge Conflict Resolver works inside the pull request and never overwrites commits someone pushed in the meantime. Free plan, 14-day Pro trial, no account needed.
Install from the Marketplace See how it works

Related guides

Not affiliated with Microsoft. “Azure DevOps” is a trademark of Microsoft. Questions? Email support@jr-devtools.com.