{"record":{"id":"f1ab776259da82e0","repo":"jdx/mise","slug":"git-failed-with-status-status","errorCode":null,"errorMessage":"git failed with status {status}","messagePattern":"git failed with status (.+?)","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/repos.rs","lineNumber":768,"sourceCode":"fn git_run(path: &Path, args: &[&str]) -> Result<()> {\n    let safe = format!(\"safe.directory={}\", path.display());\n    run_command(\n        Command::new(\"git\")\n            .arg(\"-C\")\n            .arg(path)\n            .arg(\"-c\")\n            .arg(safe)\n            .arg(\"-c\")\n            .arg(\"core.autocrlf=false\")\n            .args(args),\n    )\n}\n\nfn run_command(cmd: &mut Command) -> Result<()> {\n    debug!(\"$ {:?}\", cmd);\n    let status = cmd.status().map_err(|err| eyre!(\"git failed: {err:#}\"))?;\n    if !status.success() {\n        bail!(\"git failed with status {status}\");\n    }\n    Ok(())\n}\n\nfn print_git_command(path: &Path, args: &[&str]) -> Result<()> {\n    let mut parts = vec![\n        \"git\".to_string(),\n        \"-C\".to_string(),\n        path.display().to_string(),\n        \"-c\".to_string(),\n        format!(\"safe.directory={}\", path.display()),\n        \"-c\".to_string(),\n        \"core.autocrlf=false\".to_string(),\n    ];\n    parts.extend(args.iter().map(|arg| arg.to_string()));\n    miseprintln!(\"{}\", shell_words::join(parts));\n    Ok(())\n}","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/repos.rs#L750-L786","documentation":"run_command executes the side-effecting git operations (clone, `fetch --prune --tags`, checkout, `pull --ff-only`) without capturing output; a non-zero exit status bails as `git failed with status <code>` (e.g. exit status: 128). Because the child inherits the terminal, git's own error message appears directly above this bail in the output — read one line up for the real cause. A failure to spawn git at all produces the separate `git failed: <err>` message instead.","triggerScenarios":"`git clone` denied by auth or unreachable host; `git pull --ff-only` rejecting because the local branch diverged from origin; cloning into an existing non-empty directory; checkout of a ref that no longer exists on the remote.","commonSituations":"Local commits on a branch bootstrap tries to fast-forward; a pinned branch or tag deleted upstream but still referenced in mise.toml; SSH keys or credential helpers unavailable in cron/CI where bootstrap runs.","solutions":["Look at git's own stderr line directly above the bail — it names the concrete cause","For ff-only divergence: `git -C <repo> pull --rebase` or reset the branch to origin, then re-run","For auth/network: confirm `git ls-remote <url>` works in the same environment (SSH agent, credentials)","For stale pinned refs, update `ref` in mise.toml to a branch or tag that still exists"],"exampleFix":"# before: local commits make ff-only pull fail (status 128)\n$ git -C ~/src/x log --oneline origin/main..main   # shows local commits\n\n# after\n$ git -C ~/src/x rebase origin/main\n$ mise bootstrap","handlingStrategy":"try-catch","validationCode":"fn ff_pull_will_succeed(path: &Path, branch: &str) -> bool {\n    // local branch must not have commits missing from the remote tracking branch\n    std::process::Command::new(\"git\")\n        .arg(\"-C\").arg(path)\n        .args([\"merge-base\", \"--is-ancestor\", \"HEAD\", &format!(\"origin/{branch}\")])\n        .status()\n        .map(|s| s.success())\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match repos::update_statuses(&statuses, dry_run) {\n    Ok(()) => {}\n    Err(report) => {\n        let msg = format!(\"{report:#}\");\n        if let Some(code) = msg.strip_prefix(\"git failed with status \") {\n            // git's own stderr was streamed to the terminal above this error;\n            // exit status 128 usually means ref/network/clone failure —\n            // rerun the exact printed command to reproduce\n        }\n    }\n}","preventionTips":["Use `--dry-run` first: it prints the exact git commands (with -c safe.directory=...) to reproduce manually","Never commit directly to branches bootstrap manages — let them stay pure fast-forward tracking branches","Keep pinned `ref` values pointing at branches/tags that exist upstream"],"tags":["mise","bootstrap","repos","git","subprocess","exit-code"],"backgroundTag":"git-command-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}