gastownhall/beads · error
scanning open beads for references: %w
Error message
scanning open beads for references: %w
What it means
After resolving custom statuses, sweepReferencedInTx searches all not-done issues (per the reference-scan filter) via SearchIssuesInTx to find beads that might cite the sweep candidates; a failure is wrapped as 'scanning open beads for references'. Note this same message also wraps the comment-fetch failure (error 3808), so the inner error must be read to tell which leg failed.
Source
Thrown at internal/storage/issueops/sweep.go:100
// status would under-protect and delete a bead a live bead still cites
// (issueops.SweepRequest.ProtectReferenced).
func sweepReferencedInTx(ctx context.Context, tx *sql.Tx, candidates []*types.Issue) (map[string]bool, error) {
if len(candidates) == 0 {
return nil, nil
}
candidateIDs := make(map[string]bool, len(candidates))
for _, issue := range candidates {
candidateIDs[issue.ID] = true
}
matcher := workapi.NewCandidateIDMatcher(candidateIDs)
custom, err := ResolveCustomStatusesDetailedInTx(ctx, tx)
if err != nil {
return nil, fmt.Errorf("reading custom statuses for reference scan: %w", err)
}
notDone, err := SearchIssuesInTx(ctx, tx, "", workapi.BuildSweepReferenceScanFilter(custom))
if err != nil {
return nil, fmt.Errorf("scanning open beads for references: %w", err)
}
notDoneIDs := make([]string, 0, len(notDone))
for _, issue := range notDone {
if issue != nil {
notDoneIDs = append(notDoneIDs, issue.ID)
}
}
comments, err := GetCommentsForIssuesInTx(ctx, tx, notDoneIDs)
if err != nil {
return nil, fmt.Errorf("scanning open beads for references: %w", err)
}
referenced := make(map[string]bool)
for _, issue := range notDone {
if issue == nil {
continue
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped inner error to identify the failing leg (this search vs. the comments fetch).
- Retry the sweep with a fresh transaction — both legs are read-only up to this point.
- Narrow the sweep (fewer candidates, tighter closed-before) to reduce scan cost if timing out.
- Verify schema/migrations are current, especially anything touched by the reference-scan filter.
Example fix
// before result, err := SweepInTx(ctx, tx, req) // reference scan fails mid-run // after ctx, cancel := context.WithTimeout(ctx, 5*time.Minute) defer cancel() result, err = SweepInTx(ctx, tx, req) // generous timeout for large scans
Defensive patterns
Strategy: retry
Try / catch
result, err := issueops.SweepInTx(ctx, tx, req)
if err != nil && strings.Contains(err.Error(), "scanning open beads for references") {
// read-only leg failed; reopen tx, back off, retry
return fmt.Errorf("reference scan failed, sweep aborted safely: %w", err)
} Prevention
- Use a generous context timeout for large workspaces
- Retry with fresh transactions — the scan is read-only
- Check inner error text to distinguish search vs comment failures
- Dry-run first to size the scan cost
When it happens
Trigger: SearchIssuesInTx fails while building the not-done set: missing issues table/columns, invalid SQL from BuildSweepReferenceScanFilter with unusual custom statuses, dropped connection, or cancelled context during a ProtectReferenced sweep.
Common situations: Sweeping a large workspace where the open-beads scan times out; Dolt server restart mid-sweep; custom statuses producing an unexpected filter clause; schema drift after an upgrade.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- listing sweep candidates: %w
- failed to begin transaction: %w
- failed to recompute is_blocked: %w
- failed to commit is_blocked repairs: %w
- failed to stage is_blocked repairs: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/4969ac79edb6c680.
Report an issue: GitHub.