gitbutlerapp/gitbutler · error
Failed to remove label
Error message
Failed to remove label: {} What it means
The label-removal function DELETEs a single label from a PR; any non-success HTTP status bails with this message and the response error body. Means GitHub refused the removal — usually the label or PR doesn't exist, or the token lacks write access.
Solutions
- Check the appended response error for the exact status/cause
- Ensure the token has write (pull-requests) permission
- URL-encode the label name when constructing the removal URL; treat 404 as 'already removed' if removal is idempotent in your flow
Example fix
// before
let url = format!("{base}/repos/{o}/{r}/issues/{n}/labels/{label}"); // raw label
// after
let url = format!("{base}/repos/{o}/{r}/issues/{n}/labels/{}", urlencode(label)); Defensive patterns
Strategy: try-catch
Validate before calling
let encoded = urlencode(label);
// optionally check label exists first:
// GET /repos/{o}/{r}/labels/{encoded} -> 404 means nothing to remove Try / catch
match client.remove_label_from_pull_request(owner, repo, pr, label).await {
Ok(()) => (),
Err(e) if e.to_string().contains("404") => (), // already gone: idempotent OK
Err(e) => return Err(e),
} Prevention
- URL-encode label names in removal URLs
- Treat 404 during removal as success when idempotence is desired
- Ensure the token has write access; removal is a mutating call
When it happens
Trigger: Calling the label removal API for a PR the token can't write to (403), a PR that doesn't exist (404), or a label name needing URL encoding that produced a bad URL (422/404).
Common situations: Read-only token used for a mutating call; label already removed concurrently (404); label name with spaces/slashes not URL-encoded; rate limiting.
Related errors
- Failed to add labels
- Failed to add to GitHub stack
- Failed to create GitHub stack
- Failed to get PR base repo
- Failed to get repo
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/ba62332c9e11969c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-github/src/client.rs:821
}
let labels: Vec<GitHubPrLabelApi> = response.json().await?;
Ok(labels.into_iter().map(Into::into).collect())
}
pub async fn remove_label_from_pull_request(
&self,
owner: &str,
repo: &str,
pr_number: i64,
label: &str,
) -> Result<()> {
let url = label_removal_url(&self.base_url, owner, repo, pr_number, label)?;
let response = self.client.delete(url).send().await?;
if !response.status().is_success() {
bail!("Failed to remove label: {}", response_error(response).await);
}
Ok(())
}
/// List users who can be assigned (and requested for review) on the repo.
pub async fn list_assignable_users(&self, owner: &str, repo: &str) -> Result<Vec<GitHubUser>> {
let url = format!("{}/repos/{}/{}/assignees", self.base_url, owner, repo);
Ok(self
.get_all_pages::<GitHubApiUser>(&url, 10)
.await?
.into_iter()
.map(GitHubUser::from)
.collect())
}
/// Copilot's reviewer account, or `None` where the forge has none. It canView on GitHub (pinned to 58e5313667)