gitbutlerapp/gitbutler · error

Couldn't find remote refspecs that would match

Error message

Couldn't find remote refspecs that would match {branch}

What it means

When `apply` receives a remote-tracking branch (a branch in the `Category::RemoteBranch` category) it looks up the corresponding upstream configuration to derive the local tracking branch name. If git reports no upstream/refspec mapping for that branch (`upstream_branch_and_remote_for_tracking_branch` returns `None`), the tool cannot map the remote branch to a local one and bails.

Solutions

  1. Create or fix the local branch and set its upstream: `git branch feature-x origin/feature-x` (or `git branch --set-upstream-to=origin/feature-x feature-x`).
  2. Ensure the remote's fetch refspec covers the branch: `git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'`.
  3. Apply the local tracking branch instead of the remote-tracking name.

Example fix

// before
ws.branch_apply(repo, "origin/feature-x", ...).await?;
// after
ws.branch_apply(repo, "feature-x", ...).await?; // local tracking branch
Defensive patterns

Strategy: validation

Validate before calling

if branch.starts_with("origin/") {
    let local = &branch["origin/".len()..];
    assert!(repo.try_find_reference(&local)?.is_some(), "no local tracking branch for {branch}");
}

Try / catch

// Rust
if let Err(e) = ws.branch_apply(repo, branch, ...).await {
    if e.to_string().starts_with("Couldn't find remote refspecs") {
        eprintln!("set upstream for the branch first: git branch --set-upstream-to=...");
        return Err(e);
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Calling `apply` with a remote branch like `origin/feature-x` whose local branch has no upstream configuration, or when no remote refspec (e.g. `+refs/heads/*:refs/remotes/origin/*`) matches the branch.

Common situations: Fresh clones with missing `branch.<name>.remote`/`merge` config; manually deleted local tracking branches; remotes configured with narrow fetch refspecs that exclude the branch.

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


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/ea9debd16d15d5da. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-workspace/src/branch/apply.rs:264

    let new_stack_id = new_stack_id.unwrap_or(generate_new_stack_id);
    let branch_orig = branch;
    let (mut branch_ref, mut incoming_branch_is_remote_tracking_without_local_tracking) =
        (try_find_validated_ref(repo, branch, "apply")?, false);
    if ws.is_branch_the_target_or_its_local_tracking_branch(branch) {
        bail!("Cannot add the target '{branch}' branch to its own workspace");
    }
    let mut branch = branch.to_owned();
    if branch
        .category()
        .is_some_and(|c| c == Category::RemoteBranch)
    {
        // TODO(gix): we really want to have a function to return the local tracking branch
        //            fix this in other places, too.
        let Some((upstream_branch_name, _remote_name)) =
            repo.upstream_branch_and_remote_for_tracking_branch(branch.as_ref())?
        else {
            // TODO: actually create a local trakcing branch with proper configuration.
            bail!("Couldn't find remote refspecs that would match {branch}");
        };
        // Pretend the upstream branch is also the local tracking name.
        incoming_branch_is_remote_tracking_without_local_tracking = true;
        branch = upstream_branch_name;
        branch_ref = try_find_validated_ref(repo, branch.as_ref(), "apply")?;
    }
    let head_ref_name = repo.head_name()?.map(|name| name.to_owned());
    let head_on_managed_workspace_ref = match &ws.kind {
        WorkspaceKind::Managed { ref_info }
        | WorkspaceKind::ManagedMissingWorkspaceCommit { ref_info } => head_ref_name
            .as_ref()
            .is_some_and(|head| head == &ref_info.ref_name),
        WorkspaceKind::AdHoc => false,
    };
    let branch_has_applied_metadata =
        branch_has_applied_workspace_metadata(branch.as_ref(), &ws, meta)?;
    let branch_already_applied = (ws.ref_name() == Some(branch.as_ref())
        || ws.refname_is_segment(branch.as_ref()))

View on GitHub (pinned to 58e5313667)