gastownhall/beads · error

failed to pin target directory identity: %w

Error message

failed to pin target directory identity: %w

What it means

After HEAD verification, inspectWorktreeTarget calls os.Lstat on the worktree path to pin its on-disk identity. If Lstat fails — the path does not exist or is unreadable — this wrapped error is returned. Removal cannot proceed because the target directory cannot be identified.

Source

Thrown at cmd/bd/worktree_cmd.go:1006

		"--untracked-files=all",
		"--ignore-submodules=none",
		"--ignored=matching",
	)
	if err != nil {
		return pinnedWorktreeTarget{}, fmt.Errorf("failed to inspect target cleanliness: %w", err)
	}

	headOID := strings.TrimSpace(string(headOutput))
	if headOID == "" || headOID != worktree.headOID {
		return pinnedWorktreeTarget{}, fmt.Errorf(
			"target HEAD disagrees with git worktree registry (registry %q, target %q)",
			worktree.headOID,
			headOID,
		)
	}
	pathInfo, err := os.Lstat(worktree.path)
	if err != nil {
		return pinnedWorktreeTarget{}, fmt.Errorf("failed to pin target directory identity: %w", err)
	}
	if pathInfo.Mode()&os.ModeSymlink != 0 || !pathInfo.IsDir() {
		return pinnedWorktreeTarget{}, fmt.Errorf("target path is not a real directory: %s", worktree.path)
	}
	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)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Confirm the directory exists with `ls <path>`; if gone, run `git worktree prune` and clean the bd registry entry instead of removing.
  2. If the path moved, update the registration to the new path and retry.
  3. Restore access to the parent directory or remount the volume, then retry.
  4. Stop any racing process that deletes the directory mid-operation.

Example fix

// before
bd worktree remove feature-x
// error: failed to pin target directory identity: lstat ...: no such file or directory
// after
git worktree prune
bd worktree list   # entry gone; nothing to remove
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync, statSync } from "node:fs";
if (!existsSync(worktreePath) || !statSync(worktreePath).isDirectory()) {
  throw new Error("worktree directory missing — prune registry instead of removing");
}

Prevention

When it happens

Trigger: The registered worktree directory was deleted or renamed after registry listing but before inspection; a race where another process removes the directory between listing and Lstat; permission denied on a parent directory; revalidation on a vanished directory.

Common situations: Manual `rm -rf` of a worktree without `git worktree remove`; a build/CI cleaner deleting stale directories; unmounted network volume making the path temporarily disappear; moved path in the registry.

Related errors


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