gitbutlerapp/gitbutler · error · anyhow::Error
Failed to create merge request: {status} - {error_text}
Error message
Failed to create merge request: {status} - {error_text} What it means
The POST creating a GitLab merge request returned a non-2xx status; the message includes the status and GitLab's error body, which names the exact validation failure that caused the rejection.
Source
Thrown at crates/but-gitlab/src/client.rs:288
None
};
let title = update_draft_state_in_title(params.title, params.draft);
let body = CreateMergeRequestBody {
title: &title,
description: params.body,
source_branch: params.source_branch,
target_branch: params.target_branch,
target_project_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 create merge request: {status} - {error_text}");
}
let mr: GitLabMergeRequest = response.json().await?;
Ok(mr.into())
}
pub async fn get_merge_request(
&self,
project_id: GitLabProjectId,
mr_iid: i64,
) -> Result<MergeRequest> {
let url = format!(
"{}/projects/{}/merge_requests/{}",
self.base_url, project_id, mr_iid
);
let response = self.client.get(&url).send().await?;
View on GitHub (pinned to caf1f223d3)
Solutions
- Read error_text: 'Another open merge request already exists for this source branch' - fetch and reuse the existing MR
- Verify the source branch is pushed and the target branch name exists exactly
- Check the token scope (api) and the project role (Developer or higher)
- Shorten title/description if the body reports validation limits
Example fix
// before
let mr = client.create_merge_request(project_id, ¶ms).await?;
// after
let existing = client
.list_merge_requests(project_id, State::Opened)
.await?
.into_iter()
.find(|mr| mr.source_branch == params.source_branch);
let mr = match existing {
Some(mr) => mr,
None => client.create_merge_request(project_id, ¶ms).await?,
}; Defensive patterns
Strategy: validation
Validate before calling
let existing = client
.list_merge_requests(project_id, State::Opened)
.await?
.into_iter()
.find(|mr| mr.source_branch == params.source_branch);
if existing.is_some() {
anyhow::bail!("an open MR already exists for this source branch - reuse it");
}
// also: confirm target branch exists before creating
let branches = client.list_branches(project_id).await?;
if !branches.iter().any(|b| b.name == params.target_branch) {
anyhow::bail!("target branch '{}' does not exist", params.target_branch);
} Try / catch
if let Err(e) = client.create_merge_request(project_id, ¶ms).await {
if e.to_string().contains("already exists") {
return client.list_merge_requests(project_id, State::Opened)
.await?
.into_iter()
.find(|mr| mr.source_branch == params.source_branch)
.ok_or(e); // fall back to the existing MR
}
return Err(e);
} Prevention
- Check for an open MR on the source branch before creating one
- Push the source branch and verify the target branch name first
- Use the api-scoped token with at least Developer role
When it happens
Trigger: An open MR already exists for the same source/target pair (DUPLICATE); the target branch does not exist (main vs master); the source branch was never pushed; source equals target branch; title or description exceeds limits; token lacks api scope or the role is below Developer.
Common situations: Re-running automation that already opened the MR; wrong default-branch names; forgetting to push the feature branch before creating the MR.
Related errors
- Failed to update merge request: {status} - {error_text}
- Failed to get merge request: {}
- Failed to get MR merge status: {}
- Failed to merge merge request: {}
- Failed to set merge request draft state: {status} - {error_t
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/9127b754c4f59464.
Report an issue: GitHub.