gitbutlerapp/gitbutler · error
Expected a local branch, but
Error message
Expected a local branch, but '{}' is not under refs/heads/ What it means
After finding the reference, resolve_local_branch verifies it is under refs/heads/. Any reference that is neither a local nor remote branch (e.g. a tag, stash ref, or notes ref) is rejected because `but branch update` supports only local branches.
Solutions
- Pass a local branch name that lives under refs/heads/ (check with `git branch --list <name>`).
- If you meant to operate on a tag, use the appropriate git/tag command instead of `but branch update`.
- Create a local branch if the target should be one: `git switch -c <name>`.
Example fix
// before but branch update v1.0 --to abc123 // after but branch update release-1.0 --to abc123
Defensive patterns
Strategy: validation
Validate before calling
const isBranch = execSync(`git show-ref --verify --quiet refs/heads/${name} && echo yes || echo no`).toString().trim() === 'yes';
if (!isBranch) throw new Error(`'${name}' is not a local branch under refs/heads/`); Prevention
- Verify the target is a branch, not a tag, with `git show-ref refs/heads/<name>`.
- Don't pass tags or stash/notes refs to branch commands.
- Sanitize any ref input against Category::LocalBranch expectations.
When it happens
Trigger: Passing something like a tag name (`v1.0`) or other non-branch ref to `but branch update`; try_find_reference matches the tag, whose category is not LocalBranch or RemoteBranch, hitting the fallthrough bail.
Common situations: Confusing tags with branches; passing full refs of other categories (refs/stash, refs/notes/*) copied from tooling output.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Branch ' ' not found
- Branch ' ' not found when checking for conflicts
- Expected a local branch, but
- Local branch ' ' not found
- No HEAD reference found for remote
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/e72aac67e4780177.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/command/branch/update.rs:149
}
}
fn resolve_local_branch(ctx: &but_ctx::Context, branch: &str) -> anyhow::Result<FullName> {
let candidate = normalize_local_branch_ref(branch)?;
let repo = ctx.repo.get()?;
let Some(reference) = repo.try_find_reference(candidate.as_ref())? else {
bail!("Local branch '{}' not found", candidate.shorten());
};
let reference = reference.detach();
match reference.name.category() {
Some(Category::LocalBranch) => Ok(reference.name),
Some(Category::RemoteBranch) => {
bail!(
"Expected a local branch, but '{}' is a remote-tracking branch",
reference.name.shorten()
)
}
_ => bail!(
"Expected a local branch, but '{}' is not under refs/heads/",
reference.name.shorten()
),
}
}
fn normalize_local_branch_ref(branch: &str) -> anyhow::Result<FullName> {
let full = if branch.starts_with("refs/heads/") {
branch.to_owned()
} else if branch.starts_with("refs/") {
bail!("Only local branches under refs/heads/ are supported");
} else {
format!("refs/heads/{branch}")
};
FullName::try_from(full).map_err(|err| anyhow::anyhow!("Invalid branch name: {err}"))
}
fn output_apply_result(View on GitHub (pinned to 58e5313667)