windmill-labs/windmill · error
git ${args.join(" ")} failed (exit ${status}): ${r.stderr ??
Error message
git ${args.join(" ")} failed (exit ${status}): ${r.stderr ?? ""} What it means
The internal git() helper in cli/src/utils/git.ts runs arbitrary `git <args>` via spawnSync for git-sync deploy operations (checkout of the deploy branch, staging, commit, push). When the command exits non-zero and allowFail is not set, it throws this error with the full arg list, exit code, and git's stderr. It is a generic wrapper: the stderr text identifies the real underlying git failure.
Source
Thrown at cli/src/utils/git.ts:525
if (has((t) => t === "settings")) forcedIncludes.includeSettings = true;
if (has((t) => t === "key")) forcedIncludes.includeKey = true;
}
return { extraIncludes, forcedIncludes };
}
function git(
args: string[],
opts?: { allowFail?: boolean },
): { status: number; stdout: string; stderr: string } {
const r = spawnSync("git", args, { encoding: "utf8", stdio: "pipe" });
const status = r.status ?? 1;
if (r.error) {
if (opts?.allowFail) return { status, stdout: "", stderr: String(r.error) };
throw r.error;
}
if (status !== 0 && !opts?.allowFail) {
throw new Error(
`git ${args.join(" ")} failed (exit ${status}): ${r.stderr ?? ""}`,
);
}
return { status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
}
// Checkout (or create) the dedicated deploy branch, mirroring the hub script:
// try `git checkout <branch>`, on failure create it with -b and enable
// push.autoSetupRemote so the subsequent bare `git push` targets it.
export function checkoutGitSyncDeployBranch(branch: string): void {
const existing = git(["checkout", branch], { allowFail: true });
if (existing.status === 0) {
log.info(`Switched to existing branch ${branch}`);
return;
}
git(["checkout", "-b", branch]);
git(["config", "--add", "--bool", "push.autoSetupRemote", "true"]);
log.info(`Created and switched to branch ${branch}`);View on GitHub (pinned to e474e8803c)
Solutions
- Read the stderr suffix in the message — it names the actual git failure — and address it directly.
- For push rejections: `git pull --rebase` the deploy branch (gitSyncDeployPush already retries with rebase), or resolve conflicts manually and push.
- On CI, configure git identity: `git config --global user.name/user.email` before deploying.
- Fix remote authentication (SSH key/agent, or refreshed credential helper token).
- Ensure the expected files/paths exist locally before the deploy, and that HEAD is not in a state that blocks checkout (commit or stash).
Example fix
// before: CI container without git identity git commit ... failed (exit 128): fatal: unable to auto-detect email address // after git config --global user.name "deploy-bot" git config --global user.email "deploy-bot@example.com" wmill sync push --git-sync ...
Defensive patterns
Strategy: try-catch
Validate before calling
import { spawnSync } from "node:child_process";
// Pre-flight checks before a git-sync deploy
function preflightGit(): void {
const inRepo = spawnSync("git", ["rev-parse", "--is-inside-work-tree"], { encoding: "utf8" });
if (inRepo.status !== 0) throw new Error("not inside a git work tree");
for (const [k, v] of [["user.name", null], ["user.email", null]] as const) {
const c = spawnSync("git", ["config", k], { encoding: "utf8" });
if (c.status !== 0) throw new Error(`git ${k} is not configured`);
}
const remote = spawnSync("git", ["ls-remote", "--exit-code", "origin", "HEAD"], { encoding: "utf8" });
if (remote.status !== 0) throw new Error(`cannot reach remote 'origin': ${remote.stderr}`);
} Try / catch
try {
checkoutGitSyncDeployBranch(branch);
gitSyncDeployPush(params);
} catch (e) {
if (String(e).includes("failed (exit")) {
const stderr = String(e).split("): ")[1] ?? "";
if (stderr.includes("rejected")) {
// non-fast-forward: pull --rebase the deploy branch, then retry
spawnSync("git", ["pull", "--rebase", "origin", branch]);
} else if (stderr.includes("unable to auto-detect email")) {
spawnSync("git", ["config", "--global", "user.email", "bot@example.com"]);
}
}
throw e;
} Prevention
- Configure git user.name/user.email in CI containers before deploying.
- Keep remote credentials valid (SSH agent or refreshed credential helper).
- Run `git pull --rebase` on the deploy branch before pushing when teammates deploy concurrently.
- Commit or stash local changes so checkout of the deploy branch cannot fail.
- Confirm the synced paths exist locally so `git add` does not fail.
When it happens
Trigger: Any non-zero git exit during git-sync deploy: `git checkout <branch>` failing for the -b creation path, `git add` on a missing path, `git commit` with no user identity configured, `git push` rejected (non-fast-forward, auth failure, missing upstream), or r.error being absent but status non-zero.
Common situations: git-sync deploy where the remote branch moved (push rejected, needs rebase); missing git user.name/user.email on CI containers; bad or expired credentials for the remote; target path not present locally so `git add` fails; detached HEAD or conflicting local changes blocking checkout; rerunning when the deploy branch already exists is NOT an error (checkout uses allowFail).
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
- git branch -m ${newName} failed (exit ${r.status}): ${r.stde
- ${moduleFolderPath} has no dbt_project.yml but ${scriptBaseP
- pointerErrors.join("\n")
- Invalid native trigger file path: ${filePath}. Expected form
- You can only create forks within a git repo. Forks are track
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/2479d9392982cb38.
Report an issue: GitHub.