nikivdev/code · error

git config --global --unset {} failed

Error message

git config --global --unset {} failed

What it means

`git_config_global_unset` runs `git config --global --unset core.hooksPath` and bails when git exits non-zero. The most common non-zero case is git's exit code 5: the key is not set, so there is nothing to unset.

Source

Thrown at src/push_hook.rs:205

fn git_config_global_set(key: &str, value: &Path) -> Result<()> {
    let status = Command::new("git")
        .args(["config", "--global", key, &value.to_string_lossy()])
        .status()
        .with_context(|| format!("failed to set git config {key}"))?;
    if !status.success() {
        bail!("git config --global {} failed", key);
    }
    Ok(())
}

fn git_config_global_unset(key: &str) -> Result<()> {
    let status = Command::new("git")
        .args(["config", "--global", "--unset", key])
        .status()
        .with_context(|| format!("failed to unset git config {key}"))?;
    if !status.success() {
        bail!("git config --global --unset {} failed", key);
    }
    Ok(())
}

fn resolve_repo_root() -> Result<PathBuf> {
    let output = Command::new("git")
        .args(["rev-parse", "--show-toplevel"])
        .output()
        .context("failed to resolve git repo root")?;
    if output.status.success() {
        let value = String::from_utf8_lossy(&output.stdout).trim().to_string();
        if !value.is_empty() {
            return Ok(PathBuf::from(value));
        }
    }

    env::current_dir().context("failed to resolve current directory")
}

View on GitHub (pinned to a747e741ae)

Solutions

  1. Check `git config --global --get core.hooksPath`; if unset, the goal is already achieved and the error can be ignored
  2. Verify ~/.gitconfig is writable (`ls -l ~/.gitconfig`) and fix permissions
  3. Wrap the uninstall call to tolerate git exit code 5 (key not present)
  4. Avoid running uninstall concurrently; serialize cleanup steps in CI

Example fix

// before: unconditional cleanup step fails on second run
- run: f push hooks uninstall
// after: tolerate already-unset
- run: f push hooks uninstall || git config --global --get core.hooksPath | grep -q . && exit 1 || exit 0
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: check whether the key is set before unsetting
let out = std::process::Command::new("git")
    .args(["config", "--global", "--get", "core.hooksPath"])
    .output()?;
let is_set = out.status.success() && !out.stdout.is_empty();
if !is_set { eprintln!("core.hooksPath already unset; skipping uninstall"); }

Try / catch

match uninstall_hooks() {
    Ok(()) => {},
    Err(e) if e.to_string().contains("--unset") => {
        // often just 'key not set' (git exit code 5) — treat as already-clean
        eprintln!("unset failed (possibly already unset): {e}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `uninstall_hooks` when the config pointed at by current_hooks_path matches but `git config --global --unset core.hooksPath` fails — typically because the key was already removed (race or a second uninstall run), or the global config is unwritable/corrupt.

Common situations: Running uninstall twice in a row or in parallel; uninstalling from a second shell after hooksPath was manually unset; CI cleanup steps running concurrently; read-only HOME during teardown.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/a98d77a995db9595. Report an issue: GitHub.