gitbutlerapp/gitbutler · error
Failed to update pull request
Error message
Failed to update pull request: {status} - {error_text} What it means
Thrown by send_pr_update when the HTTP PUT used to update a Bitbucket pull request (title, description, draft state, destination) returns a non-success status. The error includes both the HTTP status and the response body text, which usually contains Bitbucket's structured error explanation.
Solutions
- Check the error_text in the message for Bitbucket's specific reason (e.g. 'not found', 'forbidden', validation message)
- Verify the token has repository write permission for PR updates
- Confirm the PR id exists and the PR is still open (not merged/declined)
- Validate the update body (destination branch name, draft flag) before calling
Example fix
// before
client.set_pull_request_draft_state(workspace, repo_slug, id, true).await?;
// after
let pr = client.fetch_repo(workspace, repo_slug).await.ok(); // confirm access first
client.set_pull_request_draft_state(workspace, repo_slug, id, true).await
.map_err(|e| anyhow::anyhow!("marking PR #{id} draft: {e:#}"))?; Defensive patterns
Strategy: try-catch
Validate before calling
// ensure PR is open and token has write scope before updating let can_write = check_repo_write_scope(token)?; anyhow::ensure!(can_write, "token lacks write access for PR update");
Try / catch
match client.update_pull_request(ws, slug, id, body).await {
Err(e) if e.to_string().contains("404") => anyhow::bail!("PR #{id} no longer exists"),
Err(e) if e.to_string().contains("40") => anyhow::bail!("permission/auth problem: {e}"),
other => other?,
} Prevention
- Check PR state (open) before mutating it
- Use tokens with repository write scope
- Validate destination/draft fields before sending
- Surface error_text from the message to users — it names the exact API rejection
When it happens
Trigger: update_pull_request or set_pull_request_draft_state targets a PR id that doesn't exist (404), the token lacks write access (403/401), the payload is rejected (400 — e.g. invalid destination branch or draft state value), or the PR is in a state that can't be edited (409/500).
Common situations: Merged or declined PR being updated; bot token with read-only scope; wrong PR id after the PR was deleted; invalid reviewer/destination values in the update body.
Related errors
- Bitbucket request failed
- Bitbucket request failed
- Failed to decline pull request
- Failed to merge pull request
- Failed to create pull request
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/06a536185c37bb4e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-bitbucket/src/client.rs:406
async fn send_pr_update(
&self,
workspace: &str,
repo_slug: &str,
id: i64,
body: &UpdatePullRequestBody<'_>,
) -> Result<BitbucketPullRequest> {
let url = format!(
"{}/repositories/{}/{}/pullrequests/{}",
self.base_url,
urlencoding::encode(workspace),
urlencoding::encode(repo_slug),
id,
);
let response = self.client.put(&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 update pull request: {status} - {error_text}");
}
let pr: BitbucketApiPullRequest = response.json().await?;
Ok(pr.into())
}
pub async fn update_pull_request(
&self,
params: &UpdatePullRequestParams<'_>,
) -> Result<BitbucketPullRequest> {
let ctx = self
.fetch_pr_edit_context(params.workspace, params.repo_slug, params.id)
.await?;
let body = build_update_body(
&ctx,
params.title,
params.description,
params.target_branch,
None,View on GitHub (pinned to 58e5313667)