{"record":{"id":"1b27d8bce6c7b094","repo":"jdx/mise","slug":"git-c-failed","errorCode":null,"errorMessage":"git -C {} {} failed: {}","messagePattern":"git -C (.+?) (.+?) failed: (.+?)","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/repos.rs","lineNumber":725,"sourceCode":"\nfn pull_ref_for(git_ref: &str) -> &str {\n    git_ref.strip_prefix(\"refs/heads/\").unwrap_or(git_ref)\n}\n\nfn git_output(path: &Path, args: &[&str]) -> Result<String> {\n    let safe = format!(\"safe.directory={}\", path.display());\n    let output = 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        .output()\n        .map_err(|err| eyre!(\"git failed: {err:#}\"))?;\n    if !output.status.success() {\n        bail!(\n            \"git -C {} {} failed: {}\",\n            path.display(),\n            shell_words::join(args),\n            String::from_utf8_lossy(&output.stderr).trim()\n        );\n    }\n    Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())\n}\n\nfn git_success(path: &Path, args: &[&str]) -> Result<bool> {\n    let safe = format!(\"safe.directory={}\", path.display());\n    let status = Command::new(\"git\")\n        .arg(\"-C\")\n        .arg(path)\n        .arg(\"-c\")\n        .arg(safe)\n        .arg(\"-c\")\n        .arg(\"core.autocrlf=false\")","sourceCodeStart":707,"sourceCodeEnd":743,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/repos.rs#L707-L743","documentation":"git_output runs a git query (`status --porcelain`, `rev-parse`, `ls-remote`, `config --get remote.origin.url`) with `-c safe.directory=<path> -c core.autocrlf=false` and captures the output; a non-zero exit bails with the repo path, the joined git arguments, and git's trimmed stderr. It surfaces from is_clean during status computation and from `rev-parse --abbrev-ref HEAD` in the unpinned-update path (e.g. a repo whose HEAD is unborn); many other call sites swallow this error via `.ok()` / `unwrap_or`.","triggerScenarios":"`git status --porcelain=v1` failing on a corrupt index; `rev-parse --abbrev-ref HEAD` failing in a manually `git init`-ed repo with zero commits sitting at the target path; `ls-remote origin` failing from network or credential errors during ref-currency checks that do propagate.","commonSituations":"Expired credentials, missing SSH agent, or no network when bootstrap contacts origin; interrupted git operations leaving a corrupt index; an empty skeleton repo created by hand where bootstrap expected a clone.","solutions":["Run the exact command from the message to see the raw error: `git -C <path> -c safe.directory=<path> <args>`","For network/auth failures, verify `git -C <repo> fetch origin` works interactively in the same environment","For corrupt repositories, run `git -C <repo> fsck` and repair, or delete the directory so bootstrap re-clones","For an unborn-HEAD repo, make an initial commit or remove the directory"],"exampleFix":"# before: manual empty init at the target path\n$ git init ~/src/x && mise bootstrap   # git -C ~/src/x rev-parse --abbrev-ref HEAD failed: ...\n\n# after: let bootstrap own the clone\n$ rm -rf ~/src/x\n$ mise bootstrap","handlingStrategy":"try-catch","validationCode":"fn git_query_ok(path: &Path, args: &[&str]) -> bool {\n    std::process::Command::new(\"git\")\n        .arg(\"-C\").arg(path)\n        .args(args)\n        .output()\n        .map(|o| o.status.success())\n        .unwrap_or(false)\n}\n// a repo is safely manageable when these all succeed:\n// [\"status\", \"--porcelain=v1\"], [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"], [\"rev-parse\", \"HEAD\"]","typeGuard":"fn repo_has_commits(path: &Path) -> bool {\n    git_query_ok(path, &[\"rev-parse\", \"--verify\", \"HEAD\"])\n}","tryCatchPattern":"match repos::status(&requests) {\n    Ok(statuses) => { /* proceed with preflight/apply */ }\n    Err(report) => {\n        let msg = format!(\"{report:#}\");\n        if msg.starts_with(\"git -C \") && msg.contains(\" failed: \") {\n            // msg embeds path, git args, and git's stderr —\n            // reproduce manually and branch on the stderr content\n            // (auth vs network vs corrupt repo have different fixes)\n        }\n    }\n}","preventionTips":["Verify `git -C <repo> fetch origin` works in the bootstrap environment (SSH agent, credentials, network)","Don't leave hand-run `git init` skeletons at repo target paths — let bootstrap clone","Run `git fsck` on repos that survived an interrupted operation"],"tags":["mise","bootstrap","repos","git","subprocess"],"backgroundTag":"git-command-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}