{"record":{"id":"9127b754c4f59464","repo":"gitbutlerapp/gitbutler","slug":"failed-to-create-merge-request-status-error","errorCode":null,"errorMessage":"Failed to create merge request: {status} - {error_text}","messagePattern":"Failed to create merge request: (.+?) - (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-gitlab/src/client.rs","lineNumber":288,"sourceCode":"            None\n        };\n\n        let title = update_draft_state_in_title(params.title, params.draft);\n\n        let body = CreateMergeRequestBody {\n            title: &title,\n            description: params.body,\n            source_branch: params.source_branch,\n            target_branch: params.target_branch,\n            target_project_id,\n        };\n\n        let response = self.client.post(&url).json(&body).send().await?;\n\n        if !response.status().is_success() {\n            let status = response.status();\n            let error_text = response.text().await.unwrap_or_default();\n            bail!(\"Failed to create merge request: {status} - {error_text}\");\n        }\n\n        let mr: GitLabMergeRequest = response.json().await?;\n        Ok(mr.into())\n    }\n\n    pub async fn get_merge_request(\n        &self,\n        project_id: GitLabProjectId,\n        mr_iid: i64,\n    ) -> Result<MergeRequest> {\n        let url = format!(\n            \"{}/projects/{}/merge_requests/{}\",\n            self.base_url, project_id, mr_iid\n        );\n\n        let response = self.client.get(&url).send().await?;\n","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-gitlab/src/client.rs#L270-L306","documentation":"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.","triggerScenarios":"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.","commonSituations":"Re-running automation that already opened the MR; wrong default-branch names; forgetting to push the feature branch before creating the MR.","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"],"exampleFix":"// before\nlet mr = client.create_merge_request(project_id, &params).await?;\n\n// after\nlet existing = client\n    .list_merge_requests(project_id, State::Opened)\n    .await?\n    .into_iter()\n    .find(|mr| mr.source_branch == params.source_branch);\nlet mr = match existing {\n    Some(mr) => mr,\n    None => client.create_merge_request(project_id, &params).await?,\n};","handlingStrategy":"validation","validationCode":"let existing = client\n    .list_merge_requests(project_id, State::Opened)\n    .await?\n    .into_iter()\n    .find(|mr| mr.source_branch == params.source_branch);\nif existing.is_some() {\n    anyhow::bail!(\"an open MR already exists for this source branch - reuse it\");\n}\n// also: confirm target branch exists before creating\nlet branches = client.list_branches(project_id).await?;\nif !branches.iter().any(|b| b.name == params.target_branch) {\n    anyhow::bail!(\"target branch '{}' does not exist\", params.target_branch);\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = client.create_merge_request(project_id, &params).await {\n    if e.to_string().contains(\"already exists\") {\n        return client.list_merge_requests(project_id, State::Opened)\n            .await?\n            .into_iter()\n            .find(|mr| mr.source_branch == params.source_branch)\n            .ok_or(e); // fall back to the existing MR\n    }\n    return Err(e);\n}","preventionTips":["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"],"tags":["gitlab","merge-request","create","validation"],"backgroundTag":"gitlab-merge-request-create-failed","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}