gitbutlerapp/gitbutler · error · anyhow::Error
Failed to add to GitHub stack: {}
Error message
Failed to add to GitHub stack: {} What it means
POST /repos/{o}/{r}/stacks/{stack_number}/add returned a non-2xx status; the wrapped response explains why the given pull request(s) could not join the stack.
Source
Thrown at crates/but-github/src/stacks.rs:335
async fn add_to_stack(
&self,
owner: &str,
repo: &str,
stack_number: i64,
pull_requests: &[i64],
) -> Result<()> {
let response = self
.client
.post(format!(
"{}/repos/{owner}/{repo}/stacks/{stack_number}/add",
self.base_url
))
.json(&StackMembersBody { pull_requests })
.send()
.await?;
if !response.status().is_success() {
bail!(
"Failed to add to GitHub stack: {}",
response_error(response).await
);
}
Ok(())
}
async fn unstack(&self, owner: &str, repo: &str, stack_number: i64) -> Result<()> {
let response = self
.client
.post(format!(
"{}/repos/{owner}/{repo}/stacks/{stack_number}/unstack",
self.base_url
))
.send()
.await?;
if !response.status().is_success() {
bail!(View on GitHub (pinned to caf1f223d3)
Solutions
- Re-list stacks to refresh stack numbers before adding
- Remove the PR from its current stack before adding it to another
- Address auth or rate-limit causes indicated by the wrapped error
Defensive patterns
Strategy: try-catch
Validate before calling
let stacks = client.list_stacks(owner, repo, pr_number).await?.unwrap_or_default();
if !stacks.iter().any(|s| s.number == stack_number) {
anyhow::bail!("stack #{stack_number} no longer exists - re-list stacks");
} Try / catch
match client.add_to_stack(owner, repo, stack_number, &pr_ids).await {
Err(e) if e.to_string().starts_with("Failed to add to GitHub stack") => {
let stacks = client.list_stacks(owner, repo, pr_number).await?;
reconcile_membership(&stacks, &pr_ids)?; // repair then retry once
client.add_to_stack(owner, repo, stack_number, &pr_ids).await
}
other => other,
} Prevention
- Re-list stacks immediately before mutating them
- Remove a PR from its current stack before adding it elsewhere
- Serialize stack mutations to avoid concurrent clients
When it happens
Trigger: The stack number no longer exists; a PR is already a member of a stack; the PR is closed; missing permissions; rate limiting.
Common situations: Stale stack numbers after an unstack or reorganization; concurrent modifications by other clients.
Related errors
- Failed to list GitHub stacks: {}
- Failed to create GitHub stack: {}
- Failed to unstack GitHub stack: {}
- Could not restore all review targets after the push failed:
- GitHub GraphQL enablePullRequestAutoMerge returned an empty
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/0258bf598ea61551.
Report an issue: GitHub.