gastownhall/beads · error

not a git repository

Error message

not a git repository

What it means

ComputeRepoIDForPathWithSource computes a stable repository ID from either the git remote URL or, as fallback, the normalized repo path. When no remote is configured it falls back to path fingerprinting via mainRepoRootForPath; if that also fails (git rev-parse cannot find a repo), it concludes the path is not inside a git repository and returns this error.

Source

Thrown at internal/beads/fingerprint.go:59

// can tell a canonical remote-derived fingerprint from the path fallback
// (bd-46vla: on a synced clone without the canonical origin remote, a
// path-fallback mismatch against the stored id is cosmetic, and stamping the
// local value into the versioned metadata table propagates it to every clone).
//
// GH#2867: When running from a git worktree, the path-based fallback (no remote)
// uses the main repository root instead of the worktree root. This ensures all
// worktrees sharing a database produce the same fingerprint. Without this,
// worktree operations would compute a different repo_id and bd doctor would
// report a fingerprint mismatch.
func ComputeRepoIDForPathWithSource(repoPath string) (string, RepoIDSource, error) {
	output, err := runGitInRepo(repoPath, "config", "--get", "remote.origin.url")
	if err != nil {
		// No remote configured — fall back to path-based fingerprint.
		// Use --git-common-dir to derive the main repo root so that
		// worktrees produce the same fingerprint as the main checkout.
		repoRoot, rootErr := mainRepoRootForPath(repoPath)
		if rootErr != nil {
			return "", "", fmt.Errorf("not a git repository")
		}

		normalized := normalizedRepoPath(repoRoot)
		hash := sha256.Sum256([]byte(normalized))
		return hex.EncodeToString(hash[:16]), RepoIDSourcePath, nil
	}

	repoURL := strings.TrimSpace(string(output))
	canonical, err := canonicalizeGitURL(repoURL)
	if err != nil {
		return "", "", fmt.Errorf("failed to canonicalize URL: %w", err)
	}

	hash := sha256.Sum256([]byte(canonical))
	return hex.EncodeToString(hash[:16]), RepoIDSourceRemote, nil
}

func canonicalizeGitURL(rawURL string) (string, error) {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run `git init` in the directory (or move into an existing repository) before computing the repo ID
  2. Verify the path with `git -C <path> rev-parse --show-toplevel` to confirm it is a git repository
  3. Pass the correct repoPath to the function if a wrong path was supplied
  4. Restore a deleted .git directory from backup or re-clone

Example fix

// before
id, _ := beads.ComputeRepoIDForPath("/home/me/notes") // not a repo
// after
if _, err := os.Stat("/home/me/notes/.git"); err == nil {
    id, _ = beads.ComputeRepoIDForPath("/home/me/notes")
}
Defensive patterns

Strategy: validation

Validate before calling

func isGitRepo(p string) bool {
    cmd := exec.Command("git", "-C", p, "rev-parse", "--show-toplevel")
    return cmd.Run() == nil
}

Try / catch

id, err := beads.ComputeRepoIDForPath(path)
if err != nil && err.Error() == "not a git repository" {
    return fmt.Errorf("%s is not a git repo; run git init first", path)
}

Prevention

When it happens

Trigger: Calling ComputeRepoIDForPath/ComputeRepoIDForPathWithSource with a repoPath that is outside any git work tree, or where `git rev-parse --show-toplevel --git-common-dir` fails (no .git, bare-ish context, or git not able to resolve from that directory).

Common situations: Running bd in a plain directory that was never `git init`ed; passing a wrong/typo'd path; operating in a directory whose .git was deleted; calling the API with an empty path while the process CWD is not a repo.

Related errors


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