gitbutlerapp/gitbutler · error

Failed to merge pull request

Error message

Failed to merge pull request: {status} - {error_text}

What it means

Thrown by merge_pull_request when the HTTP POST that merges a Bitbucket pull request returns a non-success status. The message carries the HTTP status plus Bitbucket's response body, which typically explains why the merge was rejected (conflicts, unmet checks, insufficient merge strategies).

Solutions

  1. Read the error_text in the message — it names the failing merge check or conflict
  2. Re-run/repair CI checks on the PR's source commit before merging
  3. Pull/resolve merge conflicts on the source branch and push, then retry
  4. Ensure the token/account has merge permission on the repository

Example fix

// before
client.merge_pull_request(workspace, repo_slug, id, params).await?;
// after
match client.merge_pull_request(workspace, repo_slug, id, params).await {
    Ok(()) => {},
    Err(e) if e.to_string().contains("409") => anyhow::bail!("PR #{id} has conflicts; resolve and retry"),
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check: required checks green and PR open
let pr_state = get_pr_state(ws, slug, id)?;
anyhow::ensure!(pr_state == "OPEN", "PR #{id} is not open for merge");

Try / catch

match client.merge_pull_request(ws, slug, id, params).await {
    Err(e) if e.to_string().contains("conflict") || e.to_string().contains("400") => resolve_conflicts_then_retry()?,
    other => other?,
}

Prevention

When it happens

Trigger: Merging a PR that is not open (404/400), unresolved merge conflicts (400), failing required build checks or merge checks, token without write/merge permission (403), or a merge strategy the repository disallows.

Common situations: Attempting to merge after the branch moved and conflicts appeared; required CI checks failing; user token lacking merge rights; PR already merged by someone else concurrently.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/70cd431c938a7995. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-bitbucket/src/client.rs:461

        Ok(())
    }

    pub async fn merge_pull_request(&self, params: &MergePullRequestParams<'_>) -> Result<()> {
        let body = MergePullRequestBody {
            merge_strategy: params.strategy.as_str(),
        };
        let url = format!(
            "{}/repositories/{}/{}/pullrequests/{}/merge",
            self.base_url,
            urlencoding::encode(params.workspace),
            urlencoding::encode(params.repo_slug),
            params.id,
        );
        let response = self.client.post(&url).json(&body).send().await?;
        if !response.status().is_success() {
            let status = response.status();
            let error_text = response.text().await.unwrap_or_default();
            bail!("Failed to merge pull request: {status} - {error_text}");
        }
        Ok(())
    }

    /// Decline (close) a pull request.
    pub async fn decline_pull_request(
        &self,
        workspace: &str,
        repo_slug: &str,
        id: i64,
    ) -> Result<()> {
        let url = format!(
            "{}/repositories/{}/{}/pullrequests/{}/decline",
            self.base_url,
            urlencoding::encode(workspace),
            urlencoding::encode(repo_slug),
            id,
        );

View on GitHub (pinned to 58e5313667)