gastownhall/beads · warning
Failed to update external_ref for %s: %v
Error message
Failed to update external_ref for %s: %v
What it means
During a non-batch push, bd created the issue in the external tracker successfully but then failed to write the resulting external_ref back to the local store via Store.UpdateIssue. The remote issue exists but the local record is not linked to it, so the next sync would attempt to create a duplicate. This is a warning-level message counted as a sync error; the issue is still counted as Created because the external side succeeded.
Source
Thrown at internal/tracker/engine.go:1094
created, err := e.Tracker.CreateIssue(ctx, pushIssue)
if err != nil {
if isRateLimitExhausted(err) {
return stats, fmt.Errorf("sync aborted: %w", err)
}
e.warn("Failed to create %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
}
// Update local issue with external ref
ref := e.Tracker.BuildExternalRef(created)
updates := map[string]interface{}{"external_ref": ref}
if err := e.Store.UpdateIssue(ctx, issue.ID, updates, e.Actor); err != nil {
e.warn("Failed to update external_ref for %s: %v", issue.ID, err)
stats.Errors++
// Note: issue WAS created externally, so we still count Created
// but also flag the error so the user knows the link is broken
}
// Surface any partial-success warnings from the create (e.g. a
// follow-up state change that failed) through the sync result so a
// degraded push is visible rather than silently swallowed.
for _, w := range created.Warnings {
e.warn("%s (%s)", w, issue.ID)
}
// Remember what we just pushed so the next sync can skip the fetch.
e.recordPushHash(ctx, issue, ref)
stats.Created++
} else if !opts.CreateOnly || forceIDs[issue.ID] {
// Update existing external issue
extID := e.Tracker.ExtractIdentifier(extRef)
if extID == "" {
stats.Skipped++View on GitHub (pinned to 71377f2769)
Solutions
- Check the underlying storage error in the warning text (e.g. 'database is locked') and resolve the local DB issue (kill competing bd processes, wait for locks).
- Re-run `bd sync` or `bd push`; on the next pass the issue has no external_ref yet, so re-link or re-create will be attempted.
- Verify DB integrity with the storage backend's check tool (e.g. Dolt fsck / SQLite integrity_check) if errors persist.
- If duplicates appear, remove the duplicate external issue and fix the external_ref manually via `bd update`.
- Back up and repair the local store (.beads directory) if corruption is suspected.
Example fix
// before (shell): repeated lock errors during concurrent use bd sync & bd push & // after: serialize write operations bd sync bd push
Defensive patterns
Strategy: retry
Validate before calling
// before sync: confirm the local store is writable and not locked
if _, err := os.Stat(".beads"); err != nil {
log.Fatalf("no .beads store: %v", err)
}
out, _ := exec.Command("pgrep", "bd").Output()
if len(strings.TrimSpace(string(out))) > 0 { log.Println("another bd process may hold the write lock") } Try / catch
// re-run sync when stats.Errors > 0 to relink missing external_refs
stats, err := engine.Sync(ctx, opts)
if err == nil && stats.Errors > 0 {
time.Sleep(2 * time.Second)
engine.Sync(ctx, opts)
} Prevention
- Avoid concurrent bd write commands in the same repo
- Check disk space before long-running syncs
- Verify external_ref was persisted after push (bd show)
- Run bd doctor if storage errors recur
When it happens
Trigger: e.Store.UpdateIssue(ctx, issue.ID, {external_ref: ref}, e.Actor) returns an error right after a successful Tracker.CreateIssue — e.g. local DB lock, closed DB, storage driver failure, or a read-only database.
Common situations: Local database locked by another bd process during sync; disk-full or corrupted Dolt/SQLite store; running sync while a migration or compaction holds a write lock; stale database connection after a long-running push.
Related errors
- database not available: %w
- missing external ref for Linear issue %s
- creating Linear milestone epic %q: %w
- searching local issues for Linear milestone %s: %w
- get events since %v: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/70ebd9abf88d1db3.
Report an issue: GitHub.