gastownhall/beads · error
worktree containment observation is absent or invalid
Error message
worktree containment observation is absent or invalid
What it means
Prepare rejects the request because mode is Normal and facts.Containment is not one of Contained, NotContained, or ContainmentNotRequired. The containment observation (is the worktree HEAD an ancestor of the comparison target?) is missing or an invalid value, so unpushed-commit verification cannot run and the library fails closed.
Source
Thrown at internal/worktreeremove/policy.go:211
}
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 {
return Plan{}, fmt.Errorf("worktree containment observation is absent or invalid")
}
if facts.Containment != Contained {
return Plan{}, fmt.Errorf("worktree HEAD is not contained in the comparison target")
}
} else if facts.Comparator != ComparatorNotRequired || facts.Containment != ContainmentNotRequired {
return Plan{}, fmt.Errorf("worktree force-mode comparison observations are inconsistent")
}
plan := Plan{approved: true, mode: request.Mode, targetPath: facts.RegisteredPath}
if facts.ManagedIgnore == IgnoreManaged {
plan.managedIgnoreEntry = facts.ManagedIgnoreEntry
}
return plan, nil
}
// InvariantState is the adapter's raw observation of one independently
// revalidated invariant.
type InvariantState uint8
View on GitHub (pinned to 71377f2769)
Solutions
- Set facts.Containment from an actual containment check (e.g. git merge-base --is-ancestor HEAD <comparator>)
- Ensure the adapter assigns Contained/NotContained rather than leaving the field zero
- In tests, pair ComparatorAvailable with Containment: worktreeremove.Contained
Example fix
// before facts.Containment = 0 // invalid // after facts.Containment = worktreeremove.Contained // after verifying HEAD is an ancestor of comparator
Defensive patterns
Strategy: validation
Validate before calling
switch facts.Containment {
case worktreeremove.Contained, worktreeremove.NotContained, worktreeremove.ContainmentNotRequired:
default:
return fmt.Errorf("containment not observed")
} Type guard
func containmentObserved(c worktreeremove.Containment) bool {
return c == worktreeremove.Contained || c == worktreeremove.NotContained || c == worktreeremove.ContainmentNotRequired
} Try / catch
plan, err := worktreeremove.Prepare(req, facts)
if err != nil && strings.Contains(err.Error(), "containment observation is absent") {
return fmt.Errorf("run the containment check (merge-base --is-ancestor) first: %w", err)
} Prevention
- Always run the ancestor check after resolving the comparator
- Never leave Containment zero when Comparator is set
- Validate fact pairs (Comparator+Containment) together
When it happens
Trigger: Calling Prepare with Mode: Normal and a zero-value or out-of-range Containment, e.g. an adapter that resolved the comparator but never ran the containment check.
Common situations: Custom adapters skipping the merge-base/ancestor check; tests constructing partial facts; enum drift after adding new Containment values.
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/4ffa3075c8aeef90.
Report an issue: GitHub.