gitbutlerapp/gitbutler · error · anyhow::Error

Failed to set merge request draft state: {status} - {error_t

Error message

Failed to set merge request draft state: {status} - {error_text}

What it means

Thrown by GitLabClient::set_merge_request_draft_state when the underlying MR title update (PUT /projects/:id/merge_requests/:iid with only the title field) fails. The function works by rewriting the title: it prepends or strips the `Draft: ` prefix (see update_draft_state_in_title) rather than using a dedicated endpoint. The bail includes both the HTTP status and GitLab's response body, so the validation reason is usually readable in the message.

Source

Thrown at crates/but-gitlab/src/client.rs:468

            title: &'a str,
        }

        let url = format!(
            "{}/projects/{}/merge_requests/{}",
            self.base_url, project_id, params.mr_iid
        );

        let response = self
            .client
            .put(&url)
            .json(&UpdateMergeRequestBody { title: &next_title })
            .send()
            .await?;

        if !response.status().is_success() {
            let status = response.status();
            let error_text = response.text().await.unwrap_or_default();
            bail!("Failed to set merge request draft state: {status} - {error_text}");
        }

        Ok(())
    }

    pub async fn set_merge_request_auto_merge(
        &self,
        params: &SetMergeRequestAutoMergeParams,
    ) -> Result<()> {
        let project_id = params.project_id.clone();
        if params.enabled {
            #[derive(Serialize)]
            struct EnableAutoMergeBody {
                auto_merge: bool,
            }

            let url = format!(
                "{}/projects/{}/merge_requests/{}/merge",

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Inspect error_text in the message — GitLab states which title validation failed
  2. Re-fetch the MR and skip the toggle if it is already in the desired state (title already has/lacks the prefix)
  3. Truncate or reject titles longer than ~245 chars before adding the Draft: prefix
  4. For 404, drop the stale MR from local state; for 403, check the account can edit the MR

Example fix

// before
client.set_merge_request_draft_state(&params).await?;

// after: no-op when already in the desired state, and pre-validate the title length
let mr = client.get_merge_request(params.project_id.clone(), params.mr_iid).await?;
let wants_draft = params.draft; // true = mark as draft
let is_draft = mr.title.starts_with("Draft: ");
if is_draft != wants_draft {
    ensure!(mr.title.len() + 7 <= 255, "title too long to toggle draft prefix");
    client.set_merge_request_draft_state(&params).await?;
}
Defensive patterns

Strategy: validation

Validate before calling

// No-op when already in the desired state; guard title length before prefixing
let mr = client.get_merge_request(params.project_id.clone(), params.mr_iid).await?;
let is_draft = mr.title.starts_with("Draft: ");
ensure!(is_draft != params.draft, "nothing to toggle");
ensure!(mr.title.len() + "Draft: ".len() <= 255, "title too long for draft prefix");
client.set_merge_request_draft_state(&params).await?;

Try / catch

if let Err(err) = client.set_merge_request_draft_state(&params).await {
    if err.to_string().contains("404") { /* MR deleted meanwhile; refresh view */ }
    else { return Err(err); }
}

Prevention

When it happens

Trigger: Toggling draft state on an MR that was deleted (404); the stripped/rewritten title becomes empty or invalid and GitLab rejects it with 400; account without edit rights (403); title already at GitLab's 255-character limit so adding 'Draft: ' overflows validation; expired token (401).

Common situations: Toggle races with the user deleting or closing the MR in the web UI; very long MR titles that exceed the limit once the prefix is added; automated 'mark ready' flows running against stale MR state.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/eafc323cc2d1f9b3. Report an issue: GitHub.