{"record":{"id":"20e2cce2439ee8e3","repo":"xai-org/grok-build","slug":"git-command-failed","errorCode":null,"errorMessage":"git command failed","messagePattern":"git command failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace/src/session/git.rs","lineNumber":98,"sourceCode":"                error = %e,\n                error_kind = ?e.kind(),\n                cwd = %cwd.display(),\n                \"git_cli: Command::output() FAILED (spawn error)\"\n            );\n            return Err(e.into());\n        }\n    };\n    if output.status.success() {\n        let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();\n        tracing::debug!(exit_code = 0, stdout_len = stdout.len(), \"git_cli success\");\n        Ok(stdout)\n    } else {\n        let stderr = scrub_git_output(&String::from_utf8_lossy(&output.stderr))\n            .trim()\n            .to_string();\n        let code = output.status.code();\n        tracing::debug!(exit_code = ?code, stderr = %stderr, \"git_cli failed\");\n        Err(anyhow::anyhow!(\n            \"{}\",\n            if stderr.is_empty() {\n                \"git command failed\"\n            } else {\n                &stderr\n            }\n        ))\n    }\n}\n/// Mutating [`git_cli`]: bump the gate epoch after the attempt. Failed\n/// commands can still change the repo (`pull --rebase` conflicts, partial\n/// checkout); skipping invalidate would keep pre-mutation snapshots.\nasync fn git_cli_mut(cwd: &Path, args: &[&str]) -> Result<String> {\n    let result = git_cli(cwd, args).await;\n    super::git_gate::invalidate(cwd);\n    result\n}\n/// Run a jj CLI command and return stdout on success, or error with stderr.","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace/src/session/git.rs#L80-L116","documentation":"`git_cli` shells out to `git --no-optional-locks <args>` in a working directory and returns trimmed stdout. When git exits non-zero, the error message is the scrubbed stderr text; if git printed nothing on stderr, this generic fallback message \"git command failed\" is used instead. It surfaces for any git subcommand failure invoked through the session VCS layer (get_branch, get_upstream, get_remote_url, ahead/behind, status).","triggerScenarios":"Any `git_cli`/`git_cli_mut` call where the git process exits non-zero with empty stderr: missing repo (`.git` absent) for some commands, bad object refs, index.lock contention producing no stderr, or git killed by a signal (no exit code, empty stderr).","commonSituations":"Running in a directory that is not a git repository or a bare repo where the query fails; detached/corrupted .git; git hooks or credential helpers failing silently; concurrent operations holding the index; PATH missing git for subshells (though that is usually a spawn error, not this one).","solutions":["Run the same git command manually in the reported cwd (`git -C <cwd> status`) to see the real failure.","Confirm the directory is inside a git work tree (`git -C <cwd> rev-parse --show-toplevel`).","Remove a stale `.git/index.lock` if concurrent processes left one behind.","Re-run with `GIT_TRACE=1` to capture the underlying git error that produced empty stderr."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Check git availability and repo presence before invoking git_cli\nfn git_repo_ok(cwd: &Path) -> bool {\n    cwd.join(\".git\").exists()\n        || std::process::Command::new(\"git\")\n            .arg(\"-C\").arg(cwd)\n            .arg(\"rev-parse\").arg(\"--git-dir\")\n            .output().map(|o| o.status.success()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"// Empty-stderr failures hide the real cause; rerun the command manually for diagnosis\nmatch git_cli(cwd, &[\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]).await {\n    Ok(branch) => use_branch(branch),\n    Err(e) if e.to_string() == \"git command failed\" => {\n        eprintln!(\"git failed in {} with no stderr — run `git -C {cwd:?} status` manually\", cwd.display());\n    }\n    Err(e) => eprintln!(\"git: {e}\"), // stderr text is embedded in the message\n}","preventionTips":["Verify the cwd is inside a git work tree before issuing VCS queries.","Clear stale `.git/index.lock` after crashed git processes.","Keep git on PATH for the spawned process environment.","Capture tracing::debug logs — the exit code and scrubbed stderr are logged before the error is built."],"tags":["git","subprocess","vcs","rust"],"backgroundTag":"git-command-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}