{"record":{"id":"f749feecfcdd974a","repo":"gastownhall/beads","slug":"registered-worktree-target-is-absent-or-invalid","errorCode":null,"errorMessage":"registered worktree target is absent or invalid","messagePattern":"registered worktree target is absent or invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/worktreeremove/policy.go","lineNumber":181,"sourceCode":"}\n\nfunc (plan Plan) valid() bool {\n\treturn plan.approved && (plan.mode == Normal || plan.mode == Force) && plan.targetPath != \"\"\n}\n\n// Prepare validates the initial observations and returns an approved plan.\nfunc Prepare(request Request, facts PrepareFacts) (Plan, error) {\n\tif request.Mode != Normal && request.Mode != Force {\n\t\treturn Plan{}, fmt.Errorf(\"worktree removal mode is absent or invalid\")\n\t}\n\tswitch facts.Target {\n\tcase PrimaryWorktree:\n\t\treturn Plan{}, fmt.Errorf(\"cannot remove the primary worktree\")\n\tcase CurrentWorktree:\n\t\treturn Plan{}, fmt.Errorf(\"cannot remove the worktree containing the running command\")\n\tcase RegisteredTarget:\n\tdefault:\n\t\treturn Plan{}, fmt.Errorf(\"registered worktree target is absent or invalid\")\n\t}\n\tif facts.Registration != Present || facts.RegisteredPath == \"\" ||\n\t\tfacts.TargetDir != Present || facts.GitAdminDir != Present ||\n\t\tfacts.GitMarker != Present || facts.Head != Present {\n\t\treturn Plan{}, fmt.Errorf(\"registered worktree target is absent or invalid\")\n\t}\n\tif facts.CommonDir != Matched {\n\t\treturn Plan{}, fmt.Errorf(\"target common git directory does not match repository\")\n\t}\n\tif facts.Status != Clean && facts.Status != Dirty {\n\t\treturn Plan{}, fmt.Errorf(\"worktree cleanliness observation is absent or invalid\")\n\t}\n\tif facts.ManagedIgnore != IgnoreAbsent && facts.ManagedIgnore != IgnoreManaged {\n\t\treturn Plan{}, fmt.Errorf(\"managed ignore observation is absent or invalid\")\n\t}\n\tif (facts.ManagedIgnore == IgnoreManaged) != (facts.ManagedIgnoreEntry != \"\") {\n\t\treturn Plan{}, fmt.Errorf(\"managed ignore cleanup identity is absent or invalid\")\n\t}","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/worktreeremove/policy.go#L163-L199","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nplan, err := worktreeremove.Prepare(req, worktreeremove.PrepareFacts{\n    Target:        worktreeremove.RegisteredTarget,\n    RegisteredPath: path,\n    // Registration, TargetDir, GitAdminDir, GitMarker, Head left zero\n})\n\n// after\nfacts := observeFacts(repo, path) // sets Registration, RegisteredPath, TargetDir,\n                                  // GitAdminDir, GitMarker, Head\nfacts.Target = worktreeremove.RegisteredTarget\nplan, err := worktreeremove.Prepare(req, facts)","handlingStrategy":"validation","validationCode":"func factsComplete(f worktreeremove.PrepareFacts) bool {\n    return f.Target == worktreeremove.RegisteredTarget &&\n        f.Registration == worktreeremove.Present && f.RegisteredPath != \"\" &&\n        f.TargetDir == worktreeremove.Present && f.GitAdminDir == worktreeremove.Present &&\n        f.GitMarker == worktreeremove.Present && f.Head == worktreeremove.Present\n}","typeGuard":null,"tryCatchPattern":"plan, err := worktreeremove.Prepare(req, facts)\nif err != nil && strings.Contains(err.Error(), \"registered worktree target is absent or invalid\") {\n    return fmt.Errorf(\"target is not a fully registered worktree; re-run observation or use cleanup mode\")\n}","preventionTips":["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."],"tags":["validation","worktree","git","policy"],"backgroundTag":"missing-or-invalid-parameter","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}