zed-industries/zed · error

Branch '{}' not found

Error message

Branch '{}' not found

What it means

change_branch() first checks `refs/heads/<name>`, then `refs/remotes/<name>`; only if neither ref exists does it bail with this message. For remote branches the name must include the remote prefix (for example `origin/main`), in which case a tracking local branch is created and checked out.

Source

Thrown at crates/git/src/repository.rs:2346

                git.run(&args).await?;
                anyhow::Ok(())
            })
            .boxed()
    }

    fn checkout_branch_in_worktree(
        &self,
        branch_name: String,
        worktree_path: PathBuf,
        create: bool,
    ) -> BoxFuture<'_, Result<()>> {
        let git_binary = GitBinary::new(
            self.any_git_binary_path.clone(),
            worktree_path,
            self.path(),
            self.executor.clone(),
            self.is_trusted(),
        );

        self.executor
            .spawn(async move {
                if create {
                    git_binary.run(&["checkout", "-b", &branch_name]).await?;
                } else {
                    git_binary.run(&["checkout", &branch_name]).await?;
                }
                anyhow::Ok(())
            })
            .boxed()
    }

    fn change_branch(&self, name: String) -> BoxFuture<'_, Result<()>> {
        let git_binary = self.git_binary_in_worktree();
        self.executor
            .spawn(async move {
                let git_binary = git_binary?;

View on GitHub (pinned to 5a9b9558db)

Solutions

  1. Refresh remote state so tracking refs match reality: `git fetch --prune`.
  2. Use the qualified name `origin/<branch>` when the branch only exists on the remote.
  3. Verify before calling: `git show-ref --verify refs/heads/<name>` and `git show-ref --verify refs/remotes/<remote>/<name>`.
  4. On this error, refresh the branch list instead of retrying the same stale name.
Defensive patterns

Strategy: validation

Validate before calling

fn ref_exists(git: &GitBinary, reference: &str) -> impl Future<Output = bool> + '_ {
    async move {
        git.run(&["show-ref", "--verify", "--quiet", reference]).await.is_ok()
    }
}

let target = if ref_exists(&git, &format!("refs/heads/{name}")).await
    || ref_exists(&git, &format!("refs/remotes/{name}")).await
{
    name.clone()
} else {
    git.run(&["fetch", "--prune"]).await?;
    anyhow::ensure!(
        ref_exists(&git, &format!("refs/remotes/{name}")).await,
        "Branch '{name}' not found locally or on the remote"
    );
    name.clone()
};

Try / catch

match repo.change_branch(name.clone()).await {
    Err(e) if e.to_string().contains("not found") => {
        // refresh branch list (fetch --prune) and let the user re-pick
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling change_branch with a name that is neither a local branch nor an existing remote-tracking ref: the tracking ref was pruned (`git fetch --prune` after upstream deleted the branch), the branch was never fetched, the remote was renamed, or a local-branch form was passed when only the qualified remote form exists.

Common situations: Branch pickers showing cached/stale branch lists; after the default branch was renamed upstream; shallow clones with restricted refspecs; projects whose remotes changed and old names linger in saved state.

Related errors


AI-assisted analysis of zed-industries/zed@5a9b9558db (2026-08-20). Data as JSON: /api/errors/60babaa03c435de1. Report an issue: GitHub.