gastownhall/beads · error

git config failed: %w (output: %s)

Error message

git config failed: %w (output: %s)

What it means

configureSharedHooksPath sets git config core.hooksPath to <repoRoot>/.beads-hooks (absolute path, for worktree support). This error wraps a non-zero exit from `git config core.hooksPath`, including git's combined stderr/stdout output. It is thrown by `bd hooks install` when the underlying git command fails, e.g. a locked or corrupt config, insufficient permissions, or a multi-valued key.

Source

Thrown at cmd/bd/hooks.go:1294

	return false
}

func configureSharedHooksPath() error {
	// Set git config core.hooksPath to an absolute path pointing to .beads-hooks.
	// Using an absolute path is critical for git worktrees (GH#2414):
	// git resolves relative core.hooksPath relative to the working tree root.
	repoRoot, _ := git.GetMainRepoRoot()
	if repoRoot == "" {
		repoRoot = git.GetRepoRoot()
	}
	if repoRoot == "" {
		return fmt.Errorf("not in a git repository")
	}
	absHooksPath := filepath.Join(repoRoot, ".beads-hooks")
	cmd := exec.Command("git", "config", "core.hooksPath", absHooksPath)
	cmd.Dir = repoRoot
	if output, err := cmd.CombinedOutput(); err != nil {
		return fmt.Errorf("git config failed: %w (output: %s)", err, string(output))
	}
	return nil
}

func configureBeadsHooksPath() error {
	// Set git config core.hooksPath to an absolute path pointing to .beads/hooks.
	// Using an absolute path is critical for git worktrees (GH#2414):
	// git resolves relative core.hooksPath relative to the working tree root,
	// so in a worktree ".beads/hooks" would resolve to <worktree>/.beads/hooks/
	// which doesn't exist — the hooks live in the main repo's .beads/hooks/.
	repoRoot, _ := git.GetMainRepoRoot()
	if repoRoot == "" {
		repoRoot = git.GetRepoRoot()
	}
	if repoRoot == "" {
		return fmt.Errorf("not in a git repository")
	}
	absHooksPath := filepath.Join(repoRoot, ".beads", "hooks")

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the '(output: ...)' part of the message; it contains git's own diagnostic and usually names the exact problem.
  2. Check write permission on the repo's .git/config for the user running bd.
  3. Run `git config --get --all core.hooksPath`; if multiple values exist, remove duplicates with `git config --unset-all core.hooksPath`.
  4. Verify git works: `git -C <repoRoot> config --list` — fix any parse errors it reports.
  5. Retry `bd hooks install` after fixing.

Example fix

// before (shell, diagnosing)
$ bd hooks install
// error: git config failed: exit status 1 (output: error: could not lock config file)
// after
$ sudo chown -R $(whoami) .git/config  # or fix permissions
$ bd hooks install
Defensive patterns

Strategy: try-catch

Validate before calling

if !command.Run() { return }
out, err := exec.Command("git", "-C", repoRoot, "config", "--list").CombinedOutput()
if err != nil || !isWritable(filepath.Join(repoRoot, ".git", "config")) {
    return fmt.Errorf("git config not writable/parseable: %s", out)
}

Try / catch

if _, err := configureSharedHooksPath(); err != nil {
    var gitErr *exec.ExitError
    if errors.As(err, &gitErr) {
        log.Printf("git config failed; check .git/config permissions and duplicates: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: Running `bd hooks install` (installHooksWithOptions -> configureSharedHooksPath) in a repo where `git config core.hooksPath ...` exits non-zero: read-only or unwritable .git/config, corrupted git config file, git refusing because core.hooksPath has multiple values, or git binary missing/broken.

Common situations: CI containers running as a non-root user without write access to .git; repos with hand-edited or merge-conflicted .git/config; sandboxed environments where exec of git is blocked; a duplicated core.hooksPath entry from earlier tooling.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/3d9c84c3261ccf1f. Report an issue: GitHub.