gastownhall/beads · error

listing sweep candidates: %w

Error message

listing sweep candidates: %w

What it means

sweepInUOW lists sweep candidates by calling IssueUseCase().SearchIssues with a sweep-candidate filter and wraps any failure with 'listing sweep candidates'. The sweep cannot proceed without the candidate page, so this error aborts the whole sweep operation.

Source

Thrown at internal/storage/uow/sweeper.go:81

	return RunTxResult(ctx, s.provider, func(ctx context.Context, uw UnitOfWork) (publicops.SweepResult, string, error) {
		result, err := sweepInUOW(ctx, uw, req)
		if err != nil || result.Swept == 0 {
			// A sweep that deleted nothing labels nothing: the role promises
			// at most one history entry per call and none for a no-op.
			return result, "", err
		}
		return result, fmt.Sprintf("bd: sweep %d %s bead(s)", result.Swept, req.Tier), nil
	})
}

// sweepInUOW is the whole sweep on one unit of work, shared by the preview
// path and the committing one so the two cannot answer differently.
func sweepInUOW(ctx context.Context, uw UnitOfWork, req publicops.SweepRequest) (publicops.SweepResult, error) {
	result := publicops.SweepResult{DryRun: req.DryRun}

	page, err := uw.IssueUseCase().SearchIssues(ctx, "", workapi.BuildSweepCandidateFilter(req))
	if err != nil {
		return publicops.SweepResult{}, fmt.Errorf("listing sweep candidates: %w", err)
	}

	kept, skips := workapi.FilterSweepCandidates(page.Items, req.IDPattern, req.ClosedBefore)
	result.Skipped = skips

	if req.ProtectReferenced {
		referenced, err := sweepReferencedInUOW(ctx, uw, kept)
		if err != nil {
			return publicops.SweepResult{}, err
		}
		var count int
		kept, count, result.ReferencedIDs = workapi.PartitionSweepReferenced(kept, referenced)
		result.Skipped.Referenced = count
	}

	if len(kept) == 0 {
		return result, nil
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry the sweep; check the underlying error wrapped by %w for the SQL cause
  2. Verify database connectivity and server health
  3. Sweep in smaller batches (tighter --closed-before window) to reduce scan size
  4. Verify the database schema is current (run any bd write command to migrate on non-bts setups)

Example fix

// before
bd sweep --dry-run --closed-before 2020-01-01  # listing sweep candidates: timeout
// after
bd sweep --dry-run --closed-before 2024-01-01  # narrower window, smaller scan
Defensive patterns

Strategy: retry

Validate before calling

-- preflight: ensure schema current and the sweep query is cheap
SELECT COUNT(*) FROM issues WHERE status = 'closed' AND ...  -- estimate candidate size before sweeping

Type guard

func isSweepListingError(err error) bool {
  return err != nil && strings.Contains(err.Error(), "listing sweep candidates: ")
}

Try / catch

res, err := Sweep(ctx, req)
if isSweepListingError(err) {
  // transient or too-broad filter: narrow window and retry once
  req.ClosedBefore = narrowWindow(req.ClosedBefore)
  time.Sleep(time.Second); res, err = Sweep(ctx, req)
}
return res, err

Prevention

When it happens

Trigger: Running a sweep (publicops SweepRequest) where SearchIssues(ctx, "", BuildSweepCandidateFilter(req)) errors — SQL failure, malformed filter, connection loss, or use-case error while paging candidates.

Common situations: 'bd sweep' run against an unhealthy or unreachable Dolt server; an ID pattern / closed-before filter combination producing a bad query; concurrent migration changing schema mid-sweep; ctx timeout on a large database where the candidate scan is slow.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/225a59673e49cc63. Report an issue: GitHub.