{"record":{"id":"33640921eedd9267","repo":"gastownhall/beads","slug":"git-config-unset-core-hookspath-failed-w-outp","errorCode":null,"errorMessage":"git config --unset core.hooksPath failed: %w (output: %s)","messagePattern":"git config --unset core\\.hooksPath failed: %w \\(output: (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor/git.go","lineNumber":693,"sourceCode":"\t\treturn nil // nothing set\n\t}\n\n\tif !IsBeadsManagedHooksPath(repoRoot, hooksPath) {\n\t\treturn nil // never touch a third-party hooksPath\n\t}\n\n\tresolved := expandHookPathTilde(hooksPath)\n\tif !filepath.IsAbs(resolved) {\n\t\tresolved = filepath.Join(repoRoot, resolved)\n\t}\n\tif fileExists(resolved) {\n\t\treturn nil // target exists — nothing dangling to fix\n\t}\n\n\tcmd := exec.Command(\"git\", \"config\", \"--unset\", \"core.hooksPath\")\n\tcmd.Dir = repoRoot\n\tif output, err := cmd.CombinedOutput(); err != nil {\n\t\treturn fmt.Errorf(\"git config --unset core.hooksPath failed: %w (output: %s)\", err, strings.TrimSpace(string(output)))\n\t}\n\treturn nil\n}\n\n// getConfiguredHooksPath reads the raw core.hooksPath value from repoRoot.\n// The bool return is false when core.hooksPath is not set at all.\nfunc getConfiguredHooksPath(repoRoot string) (string, bool) {\n\tcmd := exec.Command(\"git\", \"config\", \"--get\", \"core.hooksPath\")\n\tcmd.Dir = repoRoot\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\treturn \"\", false\n\t}\n\treturn strings.TrimSpace(string(out)), true\n}\n\n// IsBeadsManagedHooksPath reports whether hooksPath is one of the values bd\n// itself writes to core.hooksPath (.beads/hooks or .beads-hooks, relative or","sourceCodeStart":675,"sourceCodeEnd":711,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor/git.go#L675-L711","documentation":"FixHooksPath repairs a dangling core.hooksPath by running `git config --unset core.hooksPath` in the repo root. When the git subprocess exits non-zero, the error (including git's combined stderr/stdout output) is wrapped with this message. It indicates git itself refused or failed to remove the config value, not that the value was absent (an absent/dangling-free case returns nil earlier).","triggerScenarios":"executing `git config --unset core.hooksPath` fails: the repo root path is wrong or not a git repository, the .git/config file is read-only or corrupted, the config is locked by another process, or core.hooksPath is set in a scope git cannot unset with the default flags (e.g. defined in a system/global config whose unset conflicts, or multiple values exist).","commonSituations":"Running `bd doctor` outside a real git work tree (cmd.Dir points at a non-repo); .git/config.lock left behind after a crashed git operation; the setting lives in ~/.gitconfig or /etc/gitconfig so a local unset misbehaves; permissions changed by a container running as a different user.","solutions":["Run the command manually in the repo (`git config --unset core.hooksPath`) and read git's own error output.","Confirm the working directory is a git repository (`git -C <repoRoot> rev-parse --git-dir`).","Remove a stale lock: delete .git/config.lock if no git process is running.","If the value is set globally/system-wide, unset it in that scope: `git config --global --unset core.hooksPath` or `git config --system --unset core.hooksPath`.","If multiple values exist, use `git config --unset-all core.hooksPath`."],"exampleFix":"// before (manual diagnosis)\n$ git config --unset core.hooksPath\nerror: could not unset key in .git/config: permission denied\n$ chmod u+w .git/config && git config --unset core.hooksPath\n\n// after\n$ bd doctor\nhooksPath fix: OK","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(filepath.Join(repoRoot, \".git\")); err != nil {\n\treturn fmt.Errorf(\"not a git repository: %s\", repoRoot)\n}\nout, err := exec.Command(\"git\", \"-C\", repoRoot, \"config\", \"--get\", \"core.hooksPath\").Output()\nif err == nil && len(out) > 0 {\n\t// hooksPath set; safe to run the fix\n}","typeGuard":null,"tryCatchPattern":"if err := FixHooksPath(repoRoot); err != nil {\n\tvar execErr *exec.ExitError\n\tif errors.As(err, &execErr) {\n\t\tlog.Printf(\"git refused unset (exit %d); run `git config --unset core.hooksPath` manually: %v\", execErr.ExitCode(), err)\n\t}\n\treturn err\n}","preventionTips":["Run bd doctor from inside a real git work tree.","Clear stale .git/config.lock files after crashed git operations.","Know which scope (local/global/system) core.hooksPath is set in before unsetting.","Avoid concurrent processes mutating .git/config."],"tags":["git","subprocess","configuration","doctor"],"backgroundTag":"git-config-unset-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}