gastownhall/beads · error
registered worktree target is absent or invalid
Error message
registered worktree target is absent or invalid
What it means
Prepare rejects a RegisteredTarget whose supporting facts are incomplete: either facts.Target is not RegisteredTarget in the switch, or one of the required Present-facts (Registration, RegisteredPath, TargetDir, GitAdminDir, GitMarker, Head) is missing/empty. Prepare refuses to plan a removal against an under-verified target — every invariant must be observed before approval.
Source
Thrown at internal/worktreeremove/policy.go:181
}
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")
}
if (facts.ManagedIgnore == IgnoreManaged) != (facts.ManagedIgnoreEntry != "") {
return Plan{}, fmt.Errorf("managed ignore cleanup identity is absent or invalid")
}View on GitHub (pinned to 71377f2769)
Solutions
- Populate PrepareFacts by running the full observation set (registration lookup, target dir stat, git admin dir, git marker, HEAD) immediately before Prepare.
- Re-gather facts if the worktree changed on disk; do not reuse cached facts from before a mutation.
- Verify the user-supplied path matches the registered worktree path exactly (filepath.Clean/abs both sides).
- If the worktree is already partially deleted, use the force/cleanup path appropriate for that state instead of a Normal removal.
Example fix
// before
plan, err := worktreeremove.Prepare(req, worktreeremove.PrepareFacts{
Target: worktreeremove.RegisteredTarget,
RegisteredPath: path,
// Registration, TargetDir, GitAdminDir, GitMarker, Head left zero
})
// after
facts := observeFacts(repo, path) // sets Registration, RegisteredPath, TargetDir,
// GitAdminDir, GitMarker, Head
facts.Target = worktreeremove.RegisteredTarget
plan, err := worktreeremove.Prepare(req, facts) Defensive patterns
Strategy: validation
Validate before calling
func factsComplete(f worktreeremove.PrepareFacts) bool {
return f.Target == worktreeremove.RegisteredTarget &&
f.Registration == worktreeremove.Present && f.RegisteredPath != "" &&
f.TargetDir == worktreeremove.Present && f.GitAdminDir == worktreeremove.Present &&
f.GitMarker == worktreeremove.Present && f.Head == worktreeremove.Present
} Try / catch
plan, err := worktreeremove.Prepare(req, facts)
if err != nil && strings.Contains(err.Error(), "registered worktree target is absent or invalid") {
return fmt.Errorf("target is not a fully registered worktree; re-run observation or use cleanup mode")
} Prevention
- Always gather all Present-facts immediately before calling Prepare; never cache across mutations.
- Handle already-deleted directories with the appropriate force/cleanup flow instead of Normal removal.
- Normalize the user-supplied path (filepath.Abs/Clean) against the registered path before probing.
- Fail loudly upstream if any observation probe errors instead of silently leaving a fact zero-valued.
When it happens
Trigger: Calling Prepare with Target: RegisteredTarget but facts such as Registration != Present, RegisteredPath == "", TargetDir/GitAdminDir/GitMarker/Head != Present; constructing PrepareFacts by hand without running the observation steps; a probe command failing upstream and its fact left zero-valued.
Common situations: Worktree directory already deleted by hand so TargetDir probes came back Absent; path passed by the user doesn't match the registered path; running the fact-gathering outside the repo so git admin dir/marker checks fail; stale facts cached from an earlier state.
Related errors
- worktree removal mode is absent or invalid
- cannot remove the primary worktree
- cannot remove the worktree containing the running command
- target git marker is not a regular file: %s
- git returned invalid commit object ID %q
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f749feecfcdd974a.
Report an issue: GitHub.