gastownhall/beads · error
updating Linear milestone epic %s: %w
Error message
updating Linear milestone epic %s: %w
What it means
Wraps st.UpdateIssue failures when syncing an already-existing Linear milestone epic in beads. If merged metadata or other fields differ, the epic is updated; a storage error there is wrapped with the epic's ID via %w.
Source
Thrown at cmd/bd/linear.go:620
if existing.Description != description {
updates["description"] = description
}
if existing.IssueType != types.TypeEpic {
updates["issue_type"] = string(types.TypeEpic)
}
if existing.ExternalRef == nil || strings.TrimSpace(*existing.ExternalRef) != ref {
updates["external_ref"] = ref
}
mergedMetadata, err := mergedLinearMilestoneMetadata(existing.Metadata, ms)
if err != nil {
return "", err
}
if string(existing.Metadata) != string(mergedMetadata) {
updates["metadata"] = mergedMetadata
}
if len(updates) > 0 {
if err := st.UpdateIssue(ctx, existing.ID, updates, actor); err != nil {
return "", fmt.Errorf("updating Linear milestone epic %s: %w", existing.ID, err)
}
}
return ref, nil
}
externalRef := ref
epic := &types.Issue{
Title: title,
Description: description,
Status: types.StatusOpen,
Priority: 2,
IssueType: types.TypeEpic,
ExternalRef: &externalRef,
Metadata: metadata,
}
if generateID != nil {
if err := generateID(ctx, epic); err != nil {
return "", fmt.Errorf("generating Linear milestone epic ID: %w", err)View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped storage error and ensure the database is reachable and not locked
- Avoid running multiple Linear syncs concurrently against the same workspace
- Re-run the sync; the update is a diff-based metadata merge and safe to retry
Defensive patterns
Strategy: retry
Validate before calling
// pre-check the epic still exists before updating
if _, err := st.GetIssue(ctx, existing.ID); err != nil {
return "", fmt.Errorf("milestone epic %s vanished: %w", existing.ID, err)
} Try / catch
err := st.UpdateIssue(ctx, existing.ID, updates, actor)
if err != nil {
if isTransient(err) { time.Sleep(backoff); return retryUpdate() }
return "", fmt.Errorf("updating Linear milestone epic %s: %w", existing.ID, err)
} Prevention
- Run only one Linear sync per workspace at a time (file lock or scheduler)
- Use exponential backoff on transient storage errors
- Verify DB connectivity before long-running sync jobs
When it happens
Trigger: Linear sync detects changes to a milestone (name/description/metadata) and calls st.UpdateIssue on the existing epic; storage returns an error — concurrent write conflict, locked DB, or the epic was deleted mid-sync.
Common situations: Two sync processes running concurrently on the same workspace; Dolt database unavailable; epic issue deleted by a user while a sync was in flight.
Related errors
- node %q: setting assignee: %w
- creating Linear milestone epic %q: %w
- searching local issues for Linear milestone %s: %w
- failed to get current claim state: %w
- ErrNotClaimable
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b43552114e235ee6.
Report an issue: GitHub.