zed-industries/zed · error
failed to add remote {url} for git repository {git_dir:?}
Error message
failed to add remote {url} for git repository {git_dir:?} What it means
Raised in `checkout_repo` (crates/extension/src/extension_builder.rs:369) after a fresh `git init`, when `git --git-dir <dir>/.git remote add origin <url>` exits non-zero, so the builder cannot register the grammar repository's URL as the `origin` remote. Since the directory was just initialized, this failure is almost always an environment problem rather than a state conflict, and the subsequent shallow `git fetch` of the pinned revision cannot succeed without the remote.
Source
Thrown at crates/extension/src/extension_builder.rs:369
.with_context(|| format!("creating grammar directory {directory:?}"))?;
let init_output = util::command::new_command("git")
.arg("init")
.current_dir(directory)
.output()
.await?;
anyhow::ensure!(
init_output.status.success(),
"failed to run `git init` in directory {directory:?}"
);
let remote_add_output = util::command::new_command("git")
.arg("--git-dir")
.arg(&git_dir)
.args(["remote", "add", "origin", url])
.output()
.await
.context("executing `git remote add`")?;
anyhow::ensure!(
remote_add_output.status.success(),
"failed to add remote {url} for git repository {git_dir:?}"
);
}
let fetch_output = util::command::new_command("git")
.arg("--git-dir")
.arg(&git_dir)
.args(["fetch", "--depth", "1", "origin", rev])
.output()
.await
.context("executing `git fetch`")?;
let checkout_output = util::command::new_command("git")
.arg("--git-dir")
.arg(&git_dir)
.args(["checkout", rev])
.current_dir(directory)View on GitHub (pinned to 9d272b0363)
Solutions
- Inspect .git/config in the grammar directory and remove any `url.*.insteadOf` global rewrites (`git config --global --unset url.ssh://... .insteadOf`) or unset GIT_CONFIG_GLOBAL conflicts, then retry the build.
- Delete the grammar directory (`rm -rf <directory>`) so the builder re-runs `git init` and `remote add` from scratch.
- Check that the parent filesystem is writable and not full (`df -h`, `mount | grep <path>`).
- Unset interfering environment variables (GIT_DIR, GIT_WORK_TREE, GIT_CONFIG_GLOBAL) in the shell before building; the builder sets GIT_CONFIG_GLOBAL=/dev/null for some calls but not all.
Example fix
// before (shell): global insteadOf rewrite breaks remote add $ git config --global url."ssh://git@corp/".insteadOf "https://github.com/" $ zed: error: failed to add remote https://github.com/tree-sitter/tree-sitter-yaml ... // after (shell): scope the rewrite only to work repos, or unset it $ git config --global --unset-all url."ssh://git@corp/".insteadOf $ rm -rf ~/.local/share/zed/extensions/work/tree-sitter-yaml
Defensive patterns
Strategy: validation
Validate before calling
// Remove git config rewrites and env interference before building
const { execSync } = require('child_process');
function precheck(url) {
delete process.env.GIT_DIR;
delete process.env.GIT_WORK_TREE;
try {
execSync(`git config --global --get-regexp 'url\..*\.insteadof'`, { stdio: 'pipe' });
console.warn('global url.insteadOf rewrites present; they may corrupt remote add');
} catch { /* none found */ }
} Try / catch
try {
await buildExtension(path);
} catch (err) {
if (String(err).includes("failed to add remote")) {
console.error("Check .git/config, url.insteadOf rewrites, and disk writability:", err.message);
}
throw err;
} Prevention
- Avoid global `url.*.insteadOf` rewrites, or scope them to specific hosts only.
- Keep grammar cache directories off cloud-synced folders (Dropbox/OneDrive) that can lock .git files.
- Unset GIT_DIR/GIT_WORK_TREE/GIT_CONFIG_GLOBAL in build environments.
- Ensure sufficient disk space before building extensions.
When it happens
Trigger: Calling `compile_grammar` -> `checkout_repo` for a grammar whose directory doesn't exist yet, where `git remote add origin <url>` fails: `git` not on PATH (process spawn failure is a distinct context error, but a non-zero status can occur if the directory is not actually a git repo, e.g. `git init` above silently skipped due to a wrapped/incompatible git binary), the .git dir is missing or corrupted between the two calls, an invalid remote name/URL rejected by git configuration (e.g. hooks/insteadOf rewriting the URL to empty), or file-system errors writing .git/config (read-only or full disk).
Common situations: Corporate git config with `url.<x>.insteadOf` or `insteadOf` rewrites corrupting the remote URL; antivirus or filesystem sync (Dropbox/OneDrive) locking .git/config on Windows; a full or read-only disk; custom GIT_DIR/GIT_CONFIG environment variables interfering with the spawned git process.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- failed to run `git init` in directory {directory:?}
- failed to fetch revision {rev} in directory {directory:?}
- grammar directory '{}' already exists, but is not a git clon
- failed to run `git init` in directory '{}'
- origin/main tip {main_sha[:12]} unavailable locally after fe
AI-assisted analysis of zed-industries/zed@9d272b0363 (2026-09-12).
Data as JSON: /api/errors/938d76bb9628cf20.
Report an issue: GitHub.