zed-industries/zed · error · anyhow::Error

git clone failed: {}

Error message

git clone failed: {}

What it means

RealFs::clone_file shells out to `git clone <repo_url>` inside the working directory and, when the child exits non-zero, bails with "git clone failed:" plus git's trimmed stderr. The error text is whatever git itself printed — it is the authoritative reason (auth, DNS, repository not found). The call runs through new_command("git"), so PATH resolution of git also matters for the preceding ? error, though this specific bail means git ran and failed.

Source

Thrown at crates/fs/src/fs.rs:1294

        let mut child = new_command("git")
            .current_dir(abs_work_directory)
            .args(["clone", "--progress", repo_url])
            .stdout(Stdio::null())
            .stderr(Stdio::piped())
            .kill_on_drop(true)
            .spawn()?;
        let stderr = child
            .stderr
            .take()
            .context("failed to read git clone progress")?;
        let stderr_output = git_clone_progress::read(stderr, |message| {
            job_tracker.update(message.into());
        })
        .await?;
        let status = child.status().await?;

        if !status.success() {
            anyhow::bail!(
                "git clone failed: {}",
                git_clone_progress::failure_message(&stderr_output)
            );
        }

        Ok(())
    }

    /// Runs `git config` with the given arguments.
    /// Will return `Ok` if the commands exit status is `0`, with the stdout
    /// contents. Otherwise returns `Err` with the stderr contents.
    async fn git_config(&self, abs_work_directory: &Path, args: Vec<String>) -> Result<String> {
        let output = new_command("git")
            .current_dir(abs_work_directory)
            .args([String::from("config")].into_iter().chain(args))
            .output()
            .await?;

View on GitHub (pinned to 9d272b0363)

Solutions

  1. Run `git clone <repo_url>` manually in a terminal and read the real stderr; fix auth (credential helper, SSH key, PAT) or the URL
  2. For HTTPS behind a proxy, ensure git's http.proxy / env is visible to the app's process
  3. Retry transient network failures after confirming connectivity
  4. If the target directory is half-cloned from a previous failure, clean it before retrying
Defensive patterns

Strategy: try-catch

Try / catch

match fs.clone_file(&dir, repo_url).await {
    Ok(()) => Ok(()),
    Err(e) if e.to_string().contains("git clone failed") => {
        // stderr text after the colon is git's own reason: act on auth/network/URL
        Err(anyhow!("clone failed, run `git clone {repo_url}` manually: {e}"))
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: fs.clone_file(work_dir, repo_url) where `git clone` exits non-zero: nonexistent/private repo, missing credentials, no network, proxy/DNS failure, or a corrupted existing directory.

Common situations: Cloning template repositories on first run (no cached credentials yet), corporate proxies rejecting git:// or https, typos in repo_url, or SSH remotes without keys in the app's environment.

Related errors


AI-assisted analysis of zed-industries/zed@9d272b0363 (2026-09-05). Data as JSON: /api/errors/6b55977f07e8c4af. Report an issue: GitHub.