gastownhall/beads · error
not a git repository: %w
Error message
not a git repository: %w
What it means
After obtaining the hostname, GetCloneIDForPath resolves the main repository root with mainRepoRootForPath (using --git-common-dir so worktrees share a clone ID, GH#2867). If that resolution fails, the error is wrapped as "not a git repository" — the given path is not inside a git work tree or the git command could not run.
Source
Thrown at internal/beads/fingerprint.go:160
// GetCloneID generates a unique ID for this specific clone (not shared with other clones)
func GetCloneID() (string, error) {
return GetCloneIDForPath("")
}
// GetCloneIDForPath generates a unique ID for the specific clone rooted at or
// containing repoPath. An empty repoPath uses the current cwd.
//
// GH#2867: Uses the main repo root (not worktree root) so that all worktrees
// sharing a database produce the same clone ID.
func GetCloneIDForPath(repoPath string) (string, error) {
hostname, err := os.Hostname()
if err != nil {
return "", fmt.Errorf("failed to get hostname: %w", err)
}
repoRoot, err := mainRepoRootForPath(repoPath)
if err != nil {
return "", fmt.Errorf("not a git repository: %w", err)
}
normalizedPath := normalizedRepoPath(repoRoot)
hash := sha256.Sum256([]byte(hostname + ":" + normalizedPath))
return hex.EncodeToString(hash[:8]), nil
}
func runGitInRepo(repoPath string, args ...string) ([]byte, error) {
cmd := exec.Command("git", args...)
if repoPath != "" {
cmd.Dir = repoPath
}
return cmd.Output()
}
// mainRepoRootForPath returns the main repository root for a given path,
// correctly handling git worktrees. For worktrees, this returns the parent
// of --git-common-dir (the main repo root), not --show-toplevel (theView on GitHub (pinned to 71377f2769)
Solutions
- Verify with `git -C <path> rev-parse --show-toplevel`; if it fails, run `git init` or clone the repo first
- Pass the correct repository path to GetCloneIDForPath
- Ensure git is installed and on PATH (`which git`)
- Restore a missing .git directory or re-clone
Example fix
// before
cloneID, err := beads.GetCloneIDForPath("/tmp/scratch")
// after
cloneID, err := beads.GetCloneIDForPath("/home/me/project") // inside a git repo
Defensive patterns
Strategy: validation
Validate before calling
if out, err := exec.Command("git", "-C", path, "rev-parse", "--is-inside-work-tree").Output(); err != nil || strings.TrimSpace(string(out)) != "true" {
// not a repo; init or clone before calling
} Try / catch
cloneID, err := beads.GetCloneIDForPath(path)
if err != nil && strings.Contains(err.Error(), "not a git repository") {
return fmt.Errorf("initialize the repo first: %w", err)
} Prevention
- Verify the target path is inside a git work tree before computing clone IDs
- Ensure git is installed and on PATH
- Pass explicit repo paths instead of relying on ambient CWD
- Restore missing .git directories promptly
When it happens
Trigger: Calling GetCloneID/GetCloneIDForPath with a repoPath outside any git repository, a deleted .git directory, or a path where `git rev-parse --show-toplevel --git-common-dir` exits non-zero (e.g. git binary missing or path unreadable).
Common situations: Pointing bd at a plain folder (notes, dotfiles dir without git); running before `git clone`/`git init` completed; typo'd path; git not installed or PATH broken so the exec fails.
Related errors
- not in a git repository
- not in a git repository
- not a git repository
- not a git repository
- failed to install hooks: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/9c120b4d73838729.
Report an issue: GitHub.