gastownhall/beads · error
Failed to update %s in %s: %v
Error message
Failed to update %s in %s: %v
What it means
During push, updating an issue that already exists in the external tracker failed. The engine logs a warning, increments stats.Errors, and continues with the next issue unless the failure is rate-limit related. This indicates the remote tracker rejected or could not process the update for this specific issue.
Source
Thrown at internal/tracker/engine.go:1152
if e.PushHooks.ContentEqual(issue, extIssue) {
// Remote already matches: record the hash so future
// runs skip the fetch above, not just the update.
e.recordPushHash(ctx, issue, extRef)
stats.Skipped++
continue
}
} else if !extIssue.UpdatedAt.Before(issue.UpdatedAt) {
stats.Skipped++ // Default: external is same or newer
continue
}
}
}
if _, err := e.Tracker.UpdateIssue(ctx, extID, pushIssue); err != nil {
if isRateLimitExhausted(err) {
return stats, fmt.Errorf("sync aborted: %w", err)
}
e.warn("Failed to update %s in %s: %v", issue.ID, e.Tracker.DisplayName(), err)
stats.Errors++
if isRateLimitedErr(err) {
e.warnRateLimitAbort(err, len(issues)-stats.Created-stats.Updated-stats.Skipped-stats.Errors)
return stats, nil
}
continue
}
// Remember what we just pushed so the next sync can skip the fetch.
e.recordPushHash(ctx, issue, extRef)
stats.Updated++
} else {
stats.Skipped++
}
}
span.SetAttributes(
attribute.Int("sync.created", stats.Created),
attribute.Int("sync.updated", stats.Updated),View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped tracker error to identify cause (404 → remote deleted, 403 → permissions, 422 → validation).
- If the remote issue was deleted, either recreate it or clear the local external_ref (`bd update <id> --external-ref=""`) so push re-creates it.
- Fix field values that violate tracker constraints (truncate descriptions, valid status names).
- Renew/repair the API token and confirm project-level edit permissions.
- Re-run `bd sync` after fixing; only affected issues will retry since successful ones are hash-skipped.
Example fix
// before: stale external_ref pointing at a deleted remote issue // after: clear the ref so the next push re-creates it bd update bd-123 --external-ref="" bd push
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: ensure the remote issue exists and is editable
extID := tracker.ExtractIdentifier(derefStr(issue.ExternalRef))
if extID == "" { skip(issue) }
if _, err := tracker.FetchIssue(ctx, extID); err != nil {
log.Printf("remote for %s unreachable: %v", issue.ID, err)
} Try / catch
// exponential backoff on rate-limited or transient update failures
for i := 0; i < 5; i++ {
stats, err := engine.Sync(ctx, opts)
if err == nil && stats.Errors == 0 { return nil }
if isRateLimitedErr(err) || isTransientErr(err) {
time.Sleep(time.Duration(1<<i) * time.Second)
continue
}
return err
} Prevention
- Verify external_refs still point at live remote issues
- Keep tokens valid and project permissions current
- Trim descriptions to tracker limits before push
- Use push-hash/ContentEqual hooks to reduce API pressure
When it happens
Trigger: e.Tracker.UpdateIssue(ctx, extID, pushIssue) returns an error for an issue with a valid external_ref — e.g. HTTP 4xx/5xx from the tracker API, validation rejection of field values, deleted remote issue, or (non-exhausted) rate limiting.
Common situations: Remote issue was deleted or moved in the tracker; auth token lacks edit permission on that project; description or field value violates tracker limits (e.g. too long); temporary 5xx or secondary rate limit from GitHub/Jira/Linear APIs.
Related errors
- %s (%s)
- Failed to re-import %s: %v
- dolt path is not executable
- database not available: %w
- initializing Azure DevOps tracker: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/007cb11d1f5cd799.
Report an issue: GitHub.