gastownhall/beads · warning

Ambiguous bootstrap match for ADO #%s: %d candidates

Error message

Ambiguous bootstrap match for ADO #%s: %d candidates

What it means

During ADO bootstrap resolution, when an external ADO issue cannot be uniquely matched to a beads issue, the resolver returns multiple candidates. If result.Candidates > 1, this warning is emitted and the issue is left unmatched so the engine does not guess — a wrong auto-link would corrupt external references.

Source

Thrown at cmd/bd/ado.go:927

			// Try bootstrap matching against indexed local issues.
			if bm != nil {
				result := bm.FindMatchIndexed(extIssue, idx)
				if result.Matched {
					// Link the existing local issue to this ADO item.
					updates := map[string]interface{}{
						"external_ref":  ref,
						"source_system": "ado:" + extIssue.ID,
					}
					if err := store.UpdateIssue(ctx, result.BeadsID, updates, actor); err == nil {
						*matchCount++
						if warn != nil {
							warn(fmt.Sprintf("Bootstrap matched ADO #%s → %s (%s)", extIssue.ID, result.BeadsID, result.MatchType))
						}
						return true // GetIssueByExternalRef will now find it.
					}
				}
				if result.Candidates > 1 && warn != nil {
					warn(fmt.Sprintf("Ambiguous bootstrap match for ADO #%s: %d candidates", extIssue.ID, result.Candidates))
				}
			}

			// No match found — skip if noCreate, otherwise let engine create.
			return !noCreate
		}
	}

	return hooks
}

// buildADOPushHooks creates PushHooks for ADO-specific push filtering.
// When --types or --states are set, local beads are filtered before pushing
// to ADO by mapping the ADO filter values to beads types/statuses.
// When noCreate is true, only issues already linked to ADO work items
// are pushed (no new work items are created).
func buildADOPushHooks(mapper tracker.FieldMapper, isExternalRef func(string) bool, filters *ado.PullFilters, noCreate bool) *tracker.PushHooks {
	var allowedTypes map[types.IssueType]bool

View on GitHub (pinned to 71377f2769)

Solutions

  1. Find and merge/close the duplicate beads issues so exactly one candidate remains, then re-run sync.
  2. Manually link the ADO item to the correct beads issue (set the external ref) so bootstrap matching is no longer needed.
  3. Tighten matching by ensuring titles/external refs are unique before bootstrap.
Defensive patterns

Strategy: validation

Validate before calling

// before bootstrap, ensure unique candidates
// e.g. check for duplicate beads issues sharing titles/external refs
if dupes := findDuplicateBeadsIssues(extIssue); len(dupes) > 1 {
	// resolve duplicates manually first
}

Prevention

When it happens

Trigger: Multiple beads issues share the same title/identity heuristic used for bootstrap matching (e.g. duplicated issues after a re-import, or two issues created from the same ADO item before external refs existed).

Common situations: Re-importing or cloning an issue database creating duplicate beads issues; fuzzy title matching hitting near-identical titles; running bootstrap matching before deduplication cleanup.

Related errors


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