{"record":{"id":"055f69a82fd89c62","repo":"gastownhall/beads","slug":"hook-files-removed-but-failed-to-reset-beads-mana","errorCode":null,"errorMessage":"hook files removed, but failed to reset beads-managed git config: %w","messagePattern":"hook files removed, but failed to reset beads-managed git config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/hooks.go","lineNumber":1381,"sourceCode":"\t\t\t\treturn fmt.Errorf(\"failed to remove %s: %w\", hookName, err)\n\t\t\t}\n\t\t\t// Restore backup if exists\n\t\t\tbackupPath := hookPath + \".backup\"\n\t\t\tif _, err := os.Stat(backupPath); err == nil {\n\t\t\t\tif err := os.Rename(backupPath, hookPath); err != nil {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"Warning: failed to restore backup for %s: %v\\n\", hookName, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Not a bd hook at all — leave it alone\n\t}\n\n\t// Reset beads-managed git config (core.hooksPath, beads.role) now that the\n\t// hook files themselves are removed. A failure here must not be a\n\t// scrolling stderr warning — bd hooks uninstall must not report success\n\t// while beads-managed config is still left behind (GH#4440).\n\tif err := resetHooksPathIfBeadsManaged(); err != nil {\n\t\treturn fmt.Errorf(\"hook files removed, but failed to reset beads-managed git config: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// resetHooksPathIfBeadsManaged unsets core.hooksPath if it points to a\n// beads-managed hooks directory (.beads/hooks or .beads-hooks), and unsets\n// beads.role. beads.role marks a repo as beads-managed independent of\n// core.hooksPath, so it is cleared unconditionally here rather than gated on\n// the hooksPath match — otherwise an uninstall that runs after core.hooksPath\n// was already cleared (e.g. by `bd doctor --fix`) would leave a stale\n// beads.role behind. A key that is already absent is not an error.\nfunc resetHooksPathIfBeadsManaged() error {\n\trepoRoot, _ := git.GetMainRepoRoot()\n\tif repoRoot == \"\" {\n\t\trepoRoot = git.GetRepoRoot()\n\t}\n\tif repoRoot == \"\" {","sourceCodeStart":1363,"sourceCodeEnd":1399,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/hooks.go#L1363-L1399","documentation":"After removing hook files, uninstallHooks calls resetHooksPathIfBeadsManaged to unset core.hooksPath (when beads-managed) and beads.role. Per GH#4440, a failure here is surfaced as a hard error rather than a warning, so uninstall does not report success while bd config keys remain.","triggerScenarios":"`bd hooks uninstall` -> resetHooksPathIfBeadsManaged returns an error from `git config --unset core.hooksPath` or `git config --unset beads.role` (unwritable config, ambiguous multi-valued key, config corruption), and uninstallHooks wraps it.","commonSituations":"Duplicated beads.role from a bad merge or hand edit (git unset refuses multiple values); read-only .git/config in CI; corrupted config file; running under a user lacking write access.","solutions":["Unset the keys manually: `git config --unset-all core.hooksPath` and `git config --unset-all beads.role`.","Check `git config --get-all beads.role` for duplicates from merges and clean them up.","Fix .git/config permissions or corruption reported in the wrapped message.","Re-run `bd hooks uninstall` to get a clean success."],"exampleFix":"// before\n$ bd hooks uninstall\n// error: hook files removed, but failed to reset beads-managed git config: beads.role: exit status 5 ...\n// after\n$ git config --unset-all beads.role\n$ bd hooks uninstall   # now succeeds","handlingStrategy":"try-catch","validationCode":"out, err := exec.Command(\"git\", \"config\", \"--get-all\", \"beads.role\").Output()\nif err == nil && len(strings.Fields(string(out))) > 1 {\n    return errors.New(\"beads.role has multiple values; run git config --unset-all beads.role first\")\n}","typeGuard":null,"tryCatchPattern":"if err := uninstallHooks(); err != nil {\n    if strings.Contains(err.Error(), \"failed to reset beads-managed git config\") {\n        exec.Command(\"git\", \"config\", \"--unset-all\", \"beads.role\").Run()\n        exec.Command(\"git\", \"config\", \"--unset-all\", \"core.hooksPath\").Run()\n    }\n    return err\n}","preventionTips":["Resolve merge conflicts in .git/config so beads.role/core.hooksPath are single-valued","Verify uninstall with `git config --get core.hooksPath` and `git config --get beads.role` returning empty","Run bd with write access to .git/config"],"tags":["git","git-config","uninstall","cleanup"],"backgroundTag":"git-config-unset-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}