gitbutlerapp/gitbutler · error
Branch not found
Error message
Branch not found: {branch_name} What it means
`absorption_plan_with_perm` computes an absorb plan from workspace stacks/assignments, filtering for the stack whose applied segment's shortened ref name equals `branch_name`. If no stack's segment matches, it throws "Branch not found: {branch_name}". It means the requested branch is not an applied segment in the current workspace.
Solutions
- List applied workspace branches (`but branch list`) and use the exact short name shown.
- Strip any `refs/heads/` prefix and remote prefixes from the branch name before calling.
- Apply the stack to the workspace first if it is unapplied.
- Verify the branch belongs to the workspace you are querying, not another worktree.
Example fix
// before absorption_plan(repo, "refs/heads/feature")?; // after absorption_plan(repo, "feature")?; // exact short branch name of an applied stack
Defensive patterns
Strategy: validation
Validate before calling
// verify the branch is an applied stack segment before planning absorb
let ws = ctx.workspace()?;
let applied = ws.stacks.iter().any(|s|
s.segments.iter().any(|seg|
seg.ref_info.as_ref().is_some_and(|ri| ri.ref_name.shorten() == branch.as_bytes())));
if !applied { return Err(anyhow::anyhow!("{branch} is not an applied workspace branch")); } Try / catch
match absorption_plan(ctx, branch) {
Err(e) if e.to_string().starts_with("Branch not found:") =>
eprintln!("apply the branch to the workspace first"),
other => other?,
} Prevention
- Use short branch names exactly as shown by workspace listing (no refs/heads/ prefix)
- Only absorb into branches currently applied in the workspace
- Refresh workspace state before selecting the target branch
When it happens
Trigger: Calling the absorption_plan API with a branch name that is not the shortened ref name of any applied stack segment — branch unapplied, branch name given with a prefix (e.g. `refs/heads/` or `origin/`), or the branch exists but has no matching `ref_info` segment.
Common situations: Absorbing into a branch that was unapplied from the workspace; passing a remote-tracking name instead of the local name; case or slash mismatches in the branch name; running before any commits exist on the stack segment.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Branch not found
- another pre-commit hook is already using the repository…
- askpass broker must be initialized
- Branch ` ` is pushed, but its remote ancestry does not…
- BUG: value must be valid ref name
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/29f9074580e42a9a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-api/src/legacy/absorb.rs:145
let all_assignments = worktree_changes.assignments;
let dependencies = worktree_changes.dependencies;
// Get the stack ID for this branch
let workspace = crate::legacy::workspace::head_info(ctx)?;
// Find the stack that contains this branch
let stack = workspace
.stacks
.iter()
.find(|stack| {
stack.segments.iter().any(|segment| {
segment
.ref_info
.as_ref()
.is_some_and(|ri| ri.ref_name.shorten() == branch_name.as_bytes())
})
})
.ok_or_else(|| anyhow::anyhow!("Branch not found: {branch_name}"))?;
let stack_id = stack.id.ok_or_else(|| anyhow::anyhow!("Stack has no ID"))?;
// Filter assignments to just this stack
let candidates: Vec<AbsorbCandidate> = all_assignments
.into_iter()
.filter(|a| a.stack_id == Some(stack_id))
.map(Into::into)
.collect();
if candidates.is_empty() {
anyhow::bail!("No uncommitted changes assigned to branch: {branch_name}");
}
(candidates, dependencies)
}
AbsorptionTarget::TreeChanges {
changes,View on GitHub (pinned to 58e5313667)