gastownhall/beads · error
searching local issues for Linear milestone %s: %w
Error message
searching local issues for Linear milestone %s: %w
What it means
findLinearMilestoneEpic falls back to a full SearchIssues scan when the milestone epic isn't found by external ref, matching issues by embedded milestone ID metadata. If that search fails, the error wraps the storage failure with the milestone ID. This is the slow-path dedup lookup during Linear milestone sync.
Source
Thrown at cmd/bd/linear.go:656
return "", fmt.Errorf("generating Linear milestone epic ID: %w", err)
}
}
if err := st.CreateIssue(ctx, epic, actor); err != nil {
return "", fmt.Errorf("creating Linear milestone epic %q: %w", title, err)
}
return ref, nil
}
func findLinearMilestoneEpic(ctx context.Context, st storage.Storage, ref, milestoneID, title string) (*types.Issue, error) {
if existing, err := st.GetIssueByExternalRef(ctx, ref); err == nil {
return existing, nil
} else if !errors.Is(err, storage.ErrNotFound) {
return nil, err
}
issues, err := st.SearchIssues(ctx, "", types.IssueFilter{})
if err != nil {
return nil, fmt.Errorf("searching local issues for Linear milestone %s: %w", milestoneID, err)
}
for _, issue := range issues {
if issueHasLinearMilestoneID(issue, milestoneID) {
return issue, nil
}
}
for _, issue := range issues {
if issue.IssueType != types.TypeEpic || !strings.EqualFold(strings.TrimSpace(issue.Title), title) {
continue
}
ref := ""
if issue.ExternalRef != nil {
ref = strings.TrimSpace(*issue.ExternalRef)
}
if ref == "" {
return issue, nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped storage error and restore DB connectivity
- Re-run the sync; the lookup is read-only and safe to retry
- If searches repeatedly fail on large workspaces, ensure the epic's external ref is set so the fast GetIssueByExternalRef path succeeds and the scan fallback is never needed
Defensive patterns
Strategy: try-catch
Validate before calling
// check storage health before the scan-heavy fallback
if err := st.Ping(ctx); err != nil {
return nil, fmt.Errorf("storage unavailable before milestone lookup: %w", err)
} Type guard
func isNotFoundErr(err error) bool { return errors.Is(err, storage.ErrNotFound) } Try / catch
issues, err := st.SearchIssues(ctx, "", types.IssueFilter{})
if err != nil {
if isTransient(err) { /* backoff and retry once */ }
return nil, fmt.Errorf("searching local issues for Linear milestone %s: %w", milestoneID, err)
} Prevention
- Ensure milestone epics always carry external refs so the fast lookup path is used
- Schedule syncs during low-load windows for very large workspaces
- Retry read-only lookups freely — they have no side effects
When it happens
Trigger: Linear milestone sync where GetIssueByExternalRef returns not-found (and not storage.ErrNotFound edge cases) and the fallback st.SearchIssues(ctx, "", IssueFilter{}) errors — storage outage, large-workspace query failure, corrupted index.
Common situations: Database unavailable during import; very large workspaces where the unfiltered search times out; storage backend misconfiguration in the workspace.
Related errors
- creating Linear milestone epic %q: %w
- database not available: %w
- failed to search issues: %w
- missing external ref for Linear issue %s
- Linear project milestone is missing id
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/fe9a888652c24e4b.
Report an issue: GitHub.