gastownhall/beads · error

cannot remove the worktree containing the running command

Error message

cannot remove the worktree containing the running command

What it means

Prepare refuses to remove the worktree that contains the currently running process (facts.Target == CurrentWorktree). Removing the checkout the command itself is executing from would pull the working directory out from under the process. Like the primary-worktree rule, this is an unconditional safety refusal evaluated before fact completeness.

Source

Thrown at internal/worktreeremove/policy.go:178

		return Cleanup{}, false
	}
	return Cleanup{Entry: plan.managedIgnoreEntry}, true
}

func (plan Plan) valid() bool {
	return plan.approved && (plan.mode == Normal || plan.mode == Force) && plan.targetPath != ""
}

// Prepare validates the initial observations and returns an approved plan.
func Prepare(request Request, facts PrepareFacts) (Plan, error) {
	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")
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run the removal from a different directory (e.g. the primary worktree or outside the repo).
  2. Detect the current-worktree condition before calling Prepare and refuse with a clear message telling the user to cd elsewhere.
  3. In automation, chdir the worker process to a neutral path before performing removals.
  4. If targeting multiple worktrees, exclude the one containing the process from the batch.

Example fix

// before
plan, err := worktreeremove.Prepare(req, facts) // facts.Target == CurrentWorktree

// after
if facts.Target == worktreeremove.CurrentWorktree {
    return fmt.Errorf("cd out of this worktree before removing it")
}
plan, err := worktreeremove.Prepare(req, facts)
Defensive patterns

Strategy: validation

Validate before calling

cwd, _ := os.Getwd()
if isWithin(cwd, targetPath) {
    return fmt.Errorf("cannot remove the worktree containing the running command; cd elsewhere first")
}

Try / catch

plan, err := worktreeremove.Prepare(req, facts)
if err != nil && strings.Contains(err.Error(), "containing the running command") {
    return fmt.Errorf("run this command from outside %s", targetPath)
}

Prevention

When it happens

Trigger: Calling Prepare with facts.Target == CurrentWorktree — typically when the caller detected that the resolved worktree path is an ancestor of os.Executable()/the cwd; running a remove command from inside the worktree being removed.

Common situations: Developer cds into a linked worktree and runs the remove command for that same path; an agent/script executes removals from inside one of the worktrees it iterates over; shells whose cwd silently resolves to the worktree being targeted.

Related errors


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