gitbutlerapp/gitbutler · error

No remote refspec maps

Error message

No remote refspec maps {} to a local branch

What it means

setup_local_tracking_configuration maps a remote-tracking branch (e.g. refs/remotes/origin/main) to a local branch via gix's upstream_branch_and_remote_for_tracking_branch. When no remote refspec in the configuration maps that tracking ref back to a local branch, the mapping is impossible and setup fails.

Solutions

  1. Restore a wildcard fetch refspec in the remote config: `git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"`
  2. Run `git remote set-url`/`git fetch origin` to re-establish standard tracking configuration
  3. Choose a remote-tracking branch that is covered by the existing refspec

Example fix

// before (config)
[remote "origin"]
  fetch = +refs/heads/main:refs/remotes/origin/main
// after (config)
[remote "origin"]
  fetch = +refs/heads/*:refs/remotes/origin/*
Defensive patterns

Strategy: validation

Validate before calling

fn has_matching_refspec(repo: &gix::Repository, tracking: &gix::refs::FullNameRef) -> anyhow::Result<bool> {
    Ok(repo.upstream_branch_and_remote_for_tracking_branch(tracking)?.is_some())
}

Try / catch

match result {
    Err(e) if e.to_string().contains("No remote refspec maps") => {
        eprintln!("fix remote fetch refspec in .git/config, then retry");
        std::process::exit(1);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling apply or local_tracking_branch with a remote_tracking_ref whose remote has no fetch refspec matching it (e.g. fetch refspec deleted or narrowed), so upstream_branch_and_remote_for_tracking_branch returns None.

Common situations: Cloning with a custom/narrowed fetch refspec like `+refs/heads/main:refs/remotes/origin/main` then trying to apply a different remote branch; hand-edited .git/config missing `+refs/heads/*:refs/remotes/origin/*`.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at crates/but-workspace/src/branch/mod.rs:563

    Ok(branch_ref)
}

/// Setup `local_tracking_ref` to track `remote_tracking_ref`, and prepare a locked configuration
/// transaction with the branch configuration added.
/// We also return the commit at which `local_tracking_ref` should be placed, which is assumed to not exist.
pub(crate) fn setup_local_tracking_configuration(
    repo: &gix::Repository,
    local_tracking_ref: &gix::refs::FullNameRef,
    remote_tracking_ref: &gix::refs::FullNameRef,
) -> anyhow::Result<(gix::config::FileTransaction, gix::ObjectId)> {
    let remote_tracking_commit_id = repo
        .find_reference(remote_tracking_ref)?
        .peel_to_commit()?
        .id();
    let Some((upstream_branch, remote)) =
        repo.upstream_branch_and_remote_for_tracking_branch(remote_tracking_ref)?
    else {
        anyhow::bail!(
            "No remote refspec maps {} to a local branch",
            remote_tracking_ref.as_bstr()
        );
    };
    let remote_name = remote
        .name()
        .expect("a remote loaded by name is never anonymous");

    let mut config = repo.config_file_mut(repo.common_dir().join("config"))?;
    let mut section =
        config.section_mut_or_create_new("branch", Some(local_tracking_ref.shorten()))?;
    // Each key only where the user has not set it: neither one nor other keys are a reason to skip.
    let remote_key = gix::config::tree::Branch::REMOTE.name;
    if section.value(remote_key).is_none() {
        section.push(remote_key, Some(remote_name.as_bstr()))?;
    }
    let merge_key = gix::config::tree::Branch::MERGE.name;
    if section.value(merge_key).is_none() {

View on GitHub (pinned to 58e5313667)