gastownhall/beads · error
worktree cleanliness observation is absent or invalid
Error message
worktree cleanliness observation is absent or invalid
What it means
Prepare rejects the request because facts.Status is neither Clean nor Dirty. The cleanliness observation was never made or holds an invalid enum value, so the library cannot apply the unclean-worktree safety policy and fails closed.
Source
Thrown at internal/worktreeremove/policy.go:192
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 {
return Plan{}, fmt.Errorf("cannot verify unpushed commits: no comparison target is available")
}
if facts.Containment != Contained && facts.Containment != NotContained && facts.Containment != ContainmentNotRequired {View on GitHub (pinned to 71377f2769)
Solutions
- Populate facts.Status with Clean or Dirty from an actual git status observation
- Fix the adapter so a failed status observation sets a defined value rather than leaving Status zero
- In tests, set Status: worktreeremove.Clean (or Dirty) explicitly
Example fix
// before
facts := worktreeremove.PrepareFacts{...} // Status left zero
// after
facts := worktreeremove.PrepareFacts{...}
facts.Status = worktreeremove.Clean // from actual git status observation Defensive patterns
Strategy: validation
Validate before calling
if facts.Status != worktreeremove.Clean && facts.Status != worktreeremove.Dirty {
return fmt.Errorf("status not observed for %s", facts.RegisteredPath)
} Type guard
func statusObserved(s worktreeremove.Status) bool {
return s == worktreeremove.Clean || s == worktreeremove.Dirty
} Try / catch
plan, err := worktreeremove.Prepare(req, facts)
if err != nil && strings.Contains(err.Error(), "cleanliness observation is absent") {
return fmt.Errorf("adapter failed to observe git status: %w", err)
} Prevention
- Have the adapter always assign a defined Status, even on observation failure paths
- Check all PrepareFacts enums in a pre-flight validator before Prepare
- In tests, never rely on zero values for enum fields
When it happens
Trigger: Calling Prepare with a zero-value Status field, or an adapter that leaves Status unset after a failed git status observation.
Common situations: Custom adapter code that skips the status check; constructing PrepareFacts in tests without Status; an enum added later and not handled in the adapter.
Related errors
- target git marker is not a regular file: %s
- git returned invalid commit object ID %q
- worktree removal mode is absent or invalid
- cannot remove the primary worktree
- cannot remove the worktree containing the running command
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f08a9fa396cf4e9f.
Report an issue: GitHub.