gastownhall/beads · error

failed to fingerprint target git marker: %w

Error message

failed to fingerprint target git marker: %w

What it means

bd fingerprints the worktree's `.git` marker file (same walk/hash routine as the gitdir) so removal can verify the target did not change between plan and execution. This error wraps any failure reading or hashing that file.

Source

Thrown at cmd/bd/worktree_cmd.go:1032

	}
	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,
		commonDir:            filepath.Clean(strings.TrimSpace(string(commonDirOutput))),
		headOID:              headOID,
		branch:               worktree.branch,
		detached:             worktree.detached,

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the file is readable: `cat <worktree>/.git`; fix permissions if needed
  2. Re-run `git worktree repair` and retry the removal
  3. Retry the command if another git process was running concurrently

Example fix

// before: marker unreadable (mode 000)
chmod u+r <worktree>/.git
// after
bd worktree remove mywt
Defensive patterns

Strategy: retry

Validate before calling

if _, err := os.ReadFile(filepath.Join(worktreePath, ".git")); err != nil {
    return fmt.Errorf("marker unreadable before removal: %w", err)
}

Try / catch

if err != nil {
    if errors.Is(err, fs.ErrPermission) || os.IsNotExist(err) {
        // re-check git worktree list / repair, then retry
    }
}

Prevention

When it happens

Trigger: `bd worktree remove <name>` or observeRevalidation when opening or reading `<worktree>/.git` fails: permission denied, deleted mid-scan, or I/O error.

Common situations: Read-only worktree mounts; the marker deleted by another process (e.g. `git worktree prune`) while bd read it; FUSE/network filesystem hiccups.

Related errors


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