gitbutlerapp/gitbutler · error · anyhow::Error

Failed to find remote branch's corresponding remote

Error message

Failed to find remote branch's corresponding remote

What it means

RemoteTrackingReference::for_ui classifies a ref under refs/remotes/ and then tries to split it into (remote-name, branch-name) by matching the path component against the configured remote names via extract_remote_name_and_short_name. This error means the ref is a remote-tracking branch (Category::RemoteBranch) but its first path segment matches none of the remotes in gix::remote::Names, so no owning remote can be determined. It is a data/consistency mismatch between an existing remote ref and the current remote configuration.

Source

Thrown at crates/but-workspace/src/ui/ref_info.rs:75

#[cfg(feature = "export-schema")]
but_schemars::register_sdk_type!(RemoteTrackingReference);

impl RemoteTrackingReference {
    /// Create a new instance from `ref_name` and `remote_names`, essentially splitting the remote
    /// name off the short name.
    pub fn for_ui(
        ref_name: gix::refs::FullName,
        remote_names: &gix::remote::Names,
    ) -> anyhow::Result<Self> {
        let (category, _short_name) = ref_name.category_and_short_name().with_context(|| {
            format!("Failed to categorize presumed remote reference '{ref_name}'")
        })?;
        if category != Category::RemoteBranch {
            bail!("Expected '{ref_name}' to be a remote tracking branch, but was {category:?}");
        }
        let (longest_remote, short_name) =
            extract_remote_name_and_short_name(ref_name.as_ref(), remote_names)
                .ok_or(anyhow::anyhow!(
                    "Failed to find remote branch's corresponding remote"
                ))
                .with_context(|| {
                    format!(
                        "Remote reference '{ref_name}' couldn't be matched with any known remote"
                    )
                })?;

        Ok(RemoteTrackingReference {
            display_name: short_name.to_str_lossy().into_owned(),
            remote_name: longest_remote,
            full_name_bytes: ref_name.into_inner(),
        })
    }
}

/// Information about the target reference, the one we want to integrate with.
#[derive(serde::Serialize, Debug, Clone)]

View on GitHub (pinned to caf1f223d3)

Solutions

  1. List configured remotes (`git remote -v`) and compare with the failing ref's prefix from the error context line ("Remote reference '...' couldn't be matched with any known remote").
  2. Prune stale tracking refs: `git remote prune <remote>` or `git fetch --prune`, then retry.
  3. If the remote was renamed, delete the old namespace: `git update-ref -d refs/remotes/<old-remote>/<branch>` (or `git remote remove <old>` if still half-configured).
  4. If the ref is legitimately hand-made, re-create it under a configured remote's namespace or add the matching remote before calling the API.

Example fix

# before: remote renamed, old tracking refs remain
$ git remote rename origin upstream   # refs/remotes/origin/* now orphaned
Error: Failed to find remote branch's corresponding remote

# after: prune the stale namespace, then retry
$ git remote prune origin 2>/dev/null; git for-each-ref --format='delete %(refname)' refs/remotes/origin | git update-ref --stdin
$ but ...   # succeeds
Defensive patterns

Strategy: validation

Validate before calling

// Before calling for_ui, check the ref prefix is a configured remote
let names: HashSet<_> = remote_names.iter().map(|n| n.as_bstr().to_str_lossy().into_owned()).collect();
let short = ref_name.as_bstr().to_str_lossy();
let prefix = short.strip_prefix("refs/remotes/")
    .and_then(|rest| rest.split('/').next());
if !prefix.map(|p| names.contains(p)).unwrap_or(false) {
    // skip or prune this stale ref instead of erroring
}

Try / catch

match RemoteTrackingReference::for_ui(ref_name, &remote_names) {
    Ok(r) => Some(r),
    Err(e) if e.to_string().contains("corresponding remote") => {
        log::warn!("skipping stale tracking ref {ref_name}");
        None // tolerate stale refs in listing code paths
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling for_ui with a ref like refs/remotes/origin-foo/feature when no remote named 'origin-foo' is configured — typical after `git remote rename origin origin2` (old refs/remotes/origin/* left behind), after `git remote remove` without pruning, or with remotes embedded in the branch name (refs/remotes/origin/feature/upstream) where the greedy/longest match fails.

Common situations: Stale remote-tracking refs after renaming or deleting a remote; refs created by tooling with a prefix that is not a real remote; refs whose short branch name itself contains slashes colliding with another remote's name; migrating clone URLs without `git remote prune`.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/dd8ba04f76c0dffc. Report an issue: GitHub.