gastownhall/beads · error

target common git directory does not match repository

Error message

target common git directory does not match repository

What it means

Prepare rejects the request because facts.CommonDir is not Matched. The target worktree's common git directory does not resolve to the same repository git directory, meaning the registered worktree belongs to (or was relinked to) a different repository. The library refuses removal to avoid deleting a worktree owned by another repo.

Source

Thrown at internal/worktreeremove/policy.go:189

	if request.Mode != Normal && request.Mode != Force {
		return Plan{}, fmt.Errorf("worktree removal mode is absent or invalid")
	}
	switch facts.Target {
	case PrimaryWorktree:
		return Plan{}, fmt.Errorf("cannot remove the primary worktree")
	case CurrentWorktree:
		return Plan{}, fmt.Errorf("cannot remove the worktree containing the running command")
	case RegisteredTarget:
	default:
		return Plan{}, fmt.Errorf("registered worktree target is absent or invalid")
	}
	if facts.Registration != Present || facts.RegisteredPath == "" ||
		facts.TargetDir != Present || facts.GitAdminDir != Present ||
		facts.GitMarker != Present || facts.Head != Present {
		return Plan{}, fmt.Errorf("registered worktree target is absent or invalid")
	}
	if facts.CommonDir != Matched {
		return Plan{}, fmt.Errorf("target common git directory does not match repository")
	}
	if facts.Status != Clean && facts.Status != Dirty {
		return Plan{}, fmt.Errorf("worktree cleanliness observation is absent or invalid")
	}
	if facts.ManagedIgnore != IgnoreAbsent && facts.ManagedIgnore != IgnoreManaged {
		return Plan{}, fmt.Errorf("managed ignore observation is absent or invalid")
	}
	if (facts.ManagedIgnore == IgnoreManaged) != (facts.ManagedIgnoreEntry != "") {
		return Plan{}, fmt.Errorf("managed ignore cleanup identity is absent or invalid")
	}
	if request.Mode != Force {
		if facts.Status != Clean {
			return Plan{}, fmt.Errorf("worktree contains modified, untracked, or ignored files")
		}
		if facts.Comparator != ComparatorAvailable && facts.Comparator != ComparatorMissing && facts.Comparator != ComparatorNotRequired {
			return Plan{}, fmt.Errorf("worktree comparison target observation is absent or invalid")
		}
		if facts.Comparator != ComparatorAvailable {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Set facts.CommonDir to Matched only after verifying the worktree's commondir resolves to the same repository
  2. Repair or re-register the worktree with git worktree repair so commondir matches
  3. If testing, include CommonDir: worktreeremove.Matched in the PrepareFacts

Example fix

// before
facts.CommonDir = worktreeremove.Unknown
// after
facts.CommonDir = worktreeremove.Matched // verify commondir matches repo first
Defensive patterns

Strategy: validation

Validate before calling

if facts.CommonDir != worktreeremove.Matched {
	return fmt.Errorf("worktree %s does not belong to this repository", facts.RegisteredPath)
}

Type guard

func commonDirMatched(f worktreeremove.PrepareFacts) bool {
	return f.CommonDir == worktreeremove.Matched
}

Try / catch

plan, err := worktreeremove.Prepare(req, facts)
if err != nil && strings.Contains(err.Error(), "common git directory does not match") {
	return fmt.Errorf("run git worktree repair or re-register the worktree: %w", err)
}

Prevention

When it happens

Trigger: Calling Prepare with PrepareFacts.CommonDir set to anything other than Matched (e.g. Mismatched or Unknown), typically produced when the worktree's .git file commondir path does not match the repository's admin dir.

Common situations: A worktree copied or moved between clones; a manually edited .git/worktrees/<name>/commondir; testing with fabricated facts that never assert CommonDir: Matched.

Related errors


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