gastownhall/beads · error
set labels: list current: %w
Error message
set labels: list current: %w
What it means
Wraps a failure from labelRepo.List inside setMany (SetLabels / SetWispLabels). SetLabels must read the current labels to compute the diff before mutating; if that read fails, the whole set operation is aborted with no changes made. The error preserves the underlying cause via %w.
Source
Thrown at internal/storage/domain/label.go:156
return nil
}
func (u *labelUseCaseImpl) SetLabels(ctx context.Context, issueID string, labels []string, actor string) error {
return u.setMany(ctx, issueID, labels, actor, false)
}
func (u *labelUseCaseImpl) SetWispLabels(ctx context.Context, wispID string, labels []string, actor string) error {
return u.setMany(ctx, wispID, labels, actor, true)
}
func (u *labelUseCaseImpl) setMany(ctx context.Context, id string, labels []string, actor string, useWisp bool) error {
if id == "" {
return fmt.Errorf("set labels: id must not be empty")
}
opts := LabelOpts{UseWispsTable: useWisp}
current, err := u.labelRepo.List(ctx, id, opts)
if err != nil {
return fmt.Errorf("set labels: list current: %w", err)
}
desired := make(map[string]bool, len(labels))
for _, l := range labels {
if l != "" {
desired[l] = true
}
}
existing := make(map[string]bool, len(current))
for _, l := range current {
existing[l] = true
if !desired[l] {
if err := u.labelRepo.Delete(ctx, id, l, actor, opts); err != nil {
return fmt.Errorf("set labels: remove %s: %w", l, err)
}
}
}
for l := range desired {
if !existing[l] {View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error for the storage root cause
- Verify database connectivity and that migrations have run
- Retry the operation — the read failed before any mutation, so it is safe to retry
- Confirm you are pointed at the correct database (right repo/dolt remote)
Example fix
// before
err := store.SetLabels(ctx, id, desired, actor) // opaque
// after
if err := store.SetLabels(ctx, id, desired, actor); err != nil {
if errors.Is(err, driverConnErr) { time.Sleep(retryBackoff); err = store.SetLabels(ctx, id, desired, actor) }
return err
} Defensive patterns
Strategy: retry
Validate before calling
// No caller-side validation applies; ensure connectivity before the call.
if _, err := store.GetLabels(ctx, id); err != nil {
return fmt.Errorf("storage unavailable before SetLabels: %w", err)
} Try / catch
err := store.SetLabels(ctx, id, desired, actor)
for i := 0; err != nil && i < 3; i++ {
time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)
err = store.SetLabels(ctx, id, desired, actor) // safe: read failed before mutation
} Prevention
- Verify database connectivity and migrations before bulk label operations
- Retry SetLabels on transient storage errors — it is diff-based and safe to re-run
- Confirm the correct database/remote is in use
- Handle driver errors at one boundary instead of scattering retries
When it happens
Trigger: SetLabels/SetWispLabels called on a valid ID but labelRepo.List fails: storage driver error, database unavailable, table missing/mis-migrated, or transaction conflict.
Common situations: Dolt/driver connectivity problems; running against a database created before labels tables existed (migration missing); transient conflicts while other agents write concurrently.
Related errors
- delete: drop labels: %w
- delete: drop wisp labels: %w
- add label %s/%s: %w
- remove label %s/%s: %w
- get labels %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b549cc6c24403a50.
Report an issue: GitHub.