gastownhall/beads · error

worktree comparison target observation is absent or invalid

Error message

worktree comparison target observation is absent or invalid

What it means

Prepare rejects the request because mode is Normal but facts.Comparator holds an invalid value (not ComparatorAvailable, ComparatorMissing, or ComparatorNotRequired). The comparison-target observation is required in normal mode so the library can verify the worktree HEAD has been pushed; an absent observation fails closed.

Source

Thrown at internal/worktreeremove/policy.go:205

	}
	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 {
			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

View on GitHub (pinned to 71377f2769)

Solutions

  1. Populate facts.Comparator with ComparatorAvailable or ComparatorMissing from an actual upstream-ref check
  2. Use ComparatorNotRequired only when the comparison is genuinely not applicable
  3. In tests, set Comparator: worktreeremove.ComparatorAvailable alongside matching Containment

Example fix

// before
facts.Comparator = 0 // invalid zero value
// after
facts.Comparator = worktreeremove.ComparatorAvailable // from upstream ref resolution
Defensive patterns

Strategy: validation

Validate before calling

switch facts.Comparator {
case worktreeremove.ComparatorAvailable, worktreeremove.ComparatorMissing, worktreeremove.ComparatorNotRequired:
default:
	return fmt.Errorf("comparator not observed")
}

Type guard

func comparatorObserved(c worktreeremove.ComparatorKind) bool {
	return c == worktreeremove.ComparatorAvailable || c == worktreeremove.ComparatorMissing || c == worktreeremove.ComparatorNotRequired
}

Try / catch

plan, err := worktreeremove.Prepare(req, facts)
if err != nil && strings.Contains(err.Error(), "comparison target observation is absent") {
	return fmt.Errorf("adapter must resolve the comparison ref first: %w", err)
}

Prevention

When it happens

Trigger: Calling Prepare with Mode: Normal and a zero-value or out-of-range Comparator, usually from an adapter that never resolved the upstream/comparison ref.

Common situations: Adapters that skip comparison resolution; tests omitting Comparator; enum drift after new ComparatorKind values.

Related errors


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