gastownhall/beads · error
failed to fingerprint target git directory: %w
Error message
failed to fingerprint target git directory: %w
What it means
bd computes a SHA-256 fingerprint of the target worktree's git directory (walk of every file: name, mode, size, mtime, content) to pin its identity before removal. This wraps any error from that walk — unreadable files/dirs, permission errors, files vanishing mid-walk, symlink read failures.
Source
Thrown at cmd/bd/worktree_cmd.go:1028
}
gitDirInfo, err := os.Lstat(gitDir)
if err != nil {
return pinnedWorktreeTarget{}, fmt.Errorf("failed to pin target git directory identity: %w", err)
}
if gitDirInfo.Mode()&os.ModeSymlink != 0 || !gitDirInfo.IsDir() {
return pinnedWorktreeTarget{}, fmt.Errorf("target git directory is not a real directory: %s", gitDir)
}
gitMarkerPath := filepath.Join(worktree.path, ".git")
gitMarkerInfo, err := os.Lstat(gitMarkerPath)
if err != nil {
return pinnedWorktreeTarget{}, fmt.Errorf("failed to pin target git marker identity: %w", err)
}
if gitMarkerInfo.Mode()&os.ModeSymlink != 0 || !gitMarkerInfo.Mode().IsRegular() {
return pinnedWorktreeTarget{}, fmt.Errorf("target git marker is not a regular file: %s", gitMarkerPath)
}
gitDirFingerprint, err := fingerprintWorktreeFilesystem(gitDir)
if err != nil {
return pinnedWorktreeTarget{}, fmt.Errorf("failed to fingerprint target git directory: %w", err)
}
gitMarkerFingerprint, err := fingerprintWorktreeFilesystem(gitMarkerPath)
if err != nil {
return pinnedWorktreeTarget{}, fmt.Errorf("failed to fingerprint target git marker: %w", err)
}
statusFingerprint, err := fingerprintWorktreeStatusPaths(worktree.path, string(statusOutput))
if err != nil {
return pinnedWorktreeTarget{}, fmt.Errorf("failed to fingerprint target changes: %w", err)
}
return pinnedWorktreeTarget{
path: filepath.Clean(worktree.path),
pathInfo: pathInfo,
gitDir: gitDir,
gitDirInfo: gitDirInfo,
gitMarkerInfo: gitMarkerInfo,
gitDirFingerprint: gitDirFingerprint,
gitMarkerFingerprint: gitMarkerFingerprint,View on GitHub (pinned to 71377f2769)
Solutions
- Fix permissions on the gitdir: `chmod -R u+rwX /repo/.git/worktrees/<name>`
- Retry the command — transient I/O races (files appearing/disappearing) often clear on a second run
- Stop processes (IDEs, sync tools) that touch the repo, or exclude it from real-time scanning
Example fix
// before ls -la /repo/.git/worktrees/mywt # root-owned index.lock // after sudo chown -R "$USER" /repo/.git/worktrees/mywt && bd worktree remove mywt
Defensive patterns
Strategy: retry
Validate before calling
// ensure the gitdir is fully readable first
return filepath.Walk(gitDir, func(p string, info os.FileInfo, err error) error {
if err != nil { return err }
return nil
}) Try / catch
if err != nil {
if errors.Is(err, fs.ErrPermission) {
// fix perms and retry once
}
time.Sleep(time.Second)
err = retryInspect() // transient walk races often clear
} Prevention
- Keep IDEs/AV/backup tools from touching .git during bd operations
- Run bd as the same user that owns the repository files
- Avoid running concurrent git commands against the same worktree
When it happens
Trigger: `bd worktree remove <name>` or observeRevalidation when `filepath.WalkDir` over the worktree's gitdir fails: permission denied, file deleted concurrently, broken stat on an entry, or an unreadable symlink.
Common situations: Root-owned files inside .git/worktrees/<name>; antivirus/backup tools touching the gitdir during the scan; NFS/network filesystems returning transient stat errors; concurrent git operations deleting metadata mid-run.
Related errors
- failed to fingerprint target git marker: %w
- failed to fingerprint target changes: %w
- git push (delete %s) failed: %s: %w
- failed to check git index lock %s: %w
- failed to read .gitignore: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3dee7f810047a9b6.
Report an issue: GitHub.