gitbutlerapp/gitbutler · error
failed to determine remote and branch name for `{branch}`
Error message
failed to determine remote and branch name for `{branch}` What it means
remote_tracking_branch_parts (crates/gitbutler-git/src/context.rs) delegates to but_core::extract_remote_name_and_short_name and errors when it returns None. That helper returns None when the ref is not a refs/remotes/* ref at all, when no configured remote name prefixes the shorthand, and when the fallback for stray remote-tracking refs fails — the fallback assumes the remote is the first slash-separated component and refuses (None) if the remaining short name itself contains a slash (e.g. refs/remotes/unknown/feature/x).
Source
Thrown at crates/gitbutler-git/src/context.rs:325
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
branch_to_remote
.iter()
.map(|(branch_name, refname, remote_branch_name)| {
(branch_name, refname.to_string(), remote_branch_name)
})
.collect::<Vec<_>>()
.serialize(serializer)
}
fn remote_tracking_branch_parts(
repo: &gix::Repository,
branch: &gix::refs::FullNameRef,
) -> Result<(String, String)> {
let (remote, short_name) = extract_remote_name_and_short_name(branch, &repo.remote_names())
.ok_or_else(|| anyhow!("failed to determine remote and branch name for `{branch}`"))?;
let short_name = std::str::from_utf8(short_name.as_ref())
.context(format!("branch name for `{branch}` is not valid UTF-8"))?
.to_owned();
Ok((remote, short_name))
}
fn now_ms() -> u128 {
UNIX_EPOCH
.elapsed()
.expect("system time is set before the Unix epoch")
.as_millis()
}
async fn handle_git_prompt_push(
prompt: String,
askpass: Option<Option<StackId>>,
) -> Option<String> {
if let Some(branch_id) = askpass {View on GitHub (pinned to caf1f223d3)
Solutions
- Prune or delete the stale ref: `git remote prune <remote>` or `git update-ref -d refs/remotes/<stale-remote>/<branch>`
- Re-register the remote whose name prefixes the ref so the primary match succeeds: `git remote add <name> <url>`
- Filter inputs: only pass refs categorized as gix::refs::Category::RemoteBranch to remote-tracking helpers
- Check the ref spelling at the call site (refs/remotes/ vs refs/heads/)
Example fix
// before
let (remote, short_name) = remote_tracking_branch_parts(&repo, branch)?;
// after: pre-filter refs that the helper cannot resolve
let names = repo.remote_names();
match but_core::extract_remote_name_and_short_name(branch, &names) {
Some((remote, short)) => (remote, short.to_string_lossy().into_owned()),
None => {
tracing::warn!("skipping unresolvable ref {}", branch.as_bstr());
continue;
}
} Defensive patterns
Strategy: validation
Validate before calling
let names = repo.remote_names();
// but_core::extract_remote_name_and_short_name returns Option — use it as the pre-check
if but_core::extract_remote_name_and_short_name(branch, &names).is_none() {
// not a resolvable remote-tracking ref: skip or report instead of calling in and failing
tracing::warn!("unresolvable remote-tracking ref {}", branch.as_bstr());
continue;
}
let (remote, short) = remote_tracking_branch_parts(&repo, branch)?; Type guard
fn is_resolvable_rtb(r: &gix::refs::FullNameRef, remotes: &gix::remote::Names) -> bool {
but_core::extract_remote_name_and_short_name(r, remotes).is_some()
} Try / catch
match remote_tracking_branch_parts(&repo, branch) {
Ok(parts) => parts,
Err(err) if err.to_string().contains("failed to determine remote and branch name") => {
tracing::warn!("stray remote-tracking ref {} — consider pruning", branch.as_bstr());
continue;
}
Err(err) => return Err(err),
} Prevention
- Prune remote-tracking refs whenever remotes are removed or renamed
- Only feed refs categorized as gix::refs::Category::RemoteBranch into remote-tracking helpers
- Prefer but_core::extract_remote_name_and_short_name directly when you need Option semantics instead of errors
When it happens
Trigger: Passing a local branch ref (refs/heads/...) or a tag to a function that only accepts remote-tracking refs; a stray RTB like refs/remotes/gone/feature/sub after the remote 'gone' was removed, whose leftover short name 'feature/sub' contains a slash; remote_names from a different repo than the ref.
Common situations: Remote removed/renamed without pruning, leaving nested remote-tracking refs; refs created by tools that write under refs/remotes/ with multi-slash names; code iterating ALL references and feeding non-RTB refs into remote_tracking_branch_parts.
Related errors
- Failed to find remote branch's corresponding remote
- Failed to find remote branch's corresponding remote
- When using Anthropic in a bring your own key configuration,
- HTTP Error ${response.statusText}: ${text}
- failed to find branch {target_branch_refname}
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/2653e23cc9aeb076.
Report an issue: GitHub.