{"record":{"id":"7a2074f1e942feae","repo":"gastownhall/beads","slug":"failed-to-create-hooks-directory-w-7a2074","errorCode":null,"errorMessage":"failed to create hooks directory: %w","messagePattern":"failed to create hooks directory: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/init_git_hooks.go","lineNumber":140,"sourceCode":"\t\t\tif !hooks[i].isBdHook {\n\t\t\t\thooks[i].isPreCommitFramework = preCommitFrameworkPattern.MatchString(hooks[i].content)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn hooks\n}\n\n// installGitHooks installs git hooks inline (no external dependencies)\nfunc installGitHooks() error {\n\thooksDir, err := git.GetGitHooksDir()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Ensure hooks directory exists\n\tif err := os.MkdirAll(hooksDir, 0750); err != nil {\n\t\treturn fmt.Errorf(\"failed to create hooks directory: %w\", err)\n\t}\n\n\t// Detect existing hooks\n\texistingHooks := detectExistingHooks()\n\n\t// Check if any non-bd hooks exist\n\thasExistingHooks := false\n\tfor _, hook := range existingHooks {\n\t\tif hook.exists && !hook.isBdHook {\n\t\t\thasExistingHooks = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Default to chaining with existing hooks (no prompting)\n\tchainHooks := hasExistingHooks\n\tif chainHooks {\n\t\t// Chain mode - rename existing hooks to .old so they can be called","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/init_git_hooks.go#L122-L158","documentation":"installGitHooks ensures the repository's git hooks directory exists with os.MkdirAll(hooksDir, 0750) before writing bd hooks. If the directory cannot be created, the mkdir error is wrapped with this message. `bd init` (hook installation) fails before any hook file is written.","triggerScenarios":"os.MkdirAll fails on the resolved hooks path — the .git directory is missing (not a git repo or bare worktree layout), the parent directory is read-only, or a non-directory file named `hooks` already exists at the target path.","commonSituations":"Running `bd init` outside a git repo where hooksDir can't be created, in a repo with a read-only .git directory (CI checkouts), or after someone replaced .git/hooks with a regular file.","solutions":["Confirm you are in a git repository with a .git directory; run `git rev-parse --git-dir` to verify.","Check that `.git/hooks` is a directory, not a file, and remove/fix it if not.","Fix permissions: ensure the .git directory is writable (chmod/chown), especially in CI or container mounts.","Install hooks manually after fixing, or skip with init's no-hooks option."],"exampleFix":"// before\n$ ls .git/hooks\nhooks: Not a directory\n// after\n$ rm -f .git/hooks && mkdir .git/hooks\n$ bd init","handlingStrategy":"validation","validationCode":"hooksDir := filepath.Join(gitDir, \"hooks\")\nif fi, err := os.Stat(hooksDir); err == nil && !fi.IsDir() {\n    return fmt.Errorf(\"%s exists and is not a directory\", hooksDir)\n}\nif fi, err := os.Stat(gitDir); err == nil && fi.Mode()&0200 == 0 {\n    return fmt.Errorf(\"%s is not writable\", gitDir)\n}","typeGuard":null,"tryCatchPattern":"if err := installGitHooks(hooksDir); err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && pe.Op == \"mkdir\" {\n        // fix .git/hooks path/permissions, then retry\n    }\n    return err\n}","preventionTips":["Run bd init only inside a real git repository (`git rev-parse --git-dir`).","Ensure CI checkouts don't mount .git read-only when hooks are needed.","Never replace .git/hooks with a regular file.","Verify hook installation with `ls -la .git/hooks` after init."],"tags":["git","hooks","filesystem"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}