gastownhall/beads · warning

Link sync ADO #%d: %v

Error message

Link sync ADO #%d: %v

What it means

pushADOLinks collects per-link errors returned by resolver.PushLinks and reports each as a 'Link sync ADO #N' warning, both appended to the returned warnings slice and passed to the warn callback. Individual failed relations do not abort the sync; the count of successfully applied links is reduced accordingly.

Source

Thrown at cmd/bd/ado.go:857

			continue
		}

		// Fetch current ADO work item to get existing relations.
		adoClient := at.ADOClient()
		items, ferr := adoClient.FetchWorkItems(ctx, []int{workItemID})
		if ferr != nil || len(items) == 0 {
			if warn != nil {
				warn(fmt.Sprintf("Failed to fetch ADO #%d for link sync: %v", workItemID, ferr))
			}
			continue
		}

		errs := resolver.PushLinks(ctx, workItemID, items[0].Relations, desired, managedTargets)
		for _, e := range errs {
			msg := fmt.Sprintf("Link sync ADO #%d: %v", workItemID, e)
			warnings = append(warnings, msg)
			if warn != nil {
				warn(msg)
			}
		}
		linkCount += len(desired) - len(errs)
	}

	return linkCount, warnings
}

// buildADOPullHooks creates PullHooks for ADO-specific pull behavior.
// When bootstrapMatch is true, incoming ADO items are matched against existing
// local issues by external_ref, source_system, and heuristic before creating
// duplicates. When noCreate is true, unmatched items are skipped entirely.
func buildADOPullHooks(ctx context.Context, at *ado.Tracker, bootstrapMatch, noCreate bool, matchCount *int, warn func(string)) *tracker.PullHooks {
	prefix := "bd"
	// YAML config takes precedence — in shared-server mode the DB
	// may belong to a different project (GH#2469).
	if p := config.GetString("issue-prefix"); p != "" {
		prefix = p

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped %v error for each offending link (permission vs conflict vs invalid relation).
  2. Grant the sync identity permission to edit the affected ADO work items.
  3. Re-run sync to resolve transient revision conflicts; resolve duplicates/stale links in beads first if the error indicates invalid relations.
Defensive patterns

Strategy: fallback

Try / catch

count, warnings := pushADOLinks(ctx, ...)
for _, w := range warnings {
	if strings.HasPrefix(w, "Link sync ADO #") {
		log.Warn(w) // retry or escalate per-link
	}
}

Prevention

When it happens

Trigger: resolver.PushLinks rejects or fails to write some relations — e.g. ADO rejects a relation type, permission denied on the work item, stale concurrent revision (409), or one desired link's counterpart no longer exists.

Common situations: Service account lacking permissions to edit certain ADO work items; work-item revision conflicts from concurrent edits; relation types unsupported by the target ADO process template.

Related errors


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