gastownhall/beads · error
failed to add to waiters: %w
Error message
failed to add to waiters: %w
What it means
This error wraps a failed tx.UpdateIssue call that persists the updated waiters list to the merge slot bead's metadata while waiting for the slot. The waiter was computed but could not be written inside the acquire transaction, so the whole transaction rolls back and the caller is not registered as waiting.
Source
Thrown at internal/storage/merge_slot.go:121
if slot.Status != types.StatusOpen {
// Slot is held.
if wait {
alreadyWaiting := false
for _, w := range meta.Waiters {
if w == holder {
alreadyWaiting = true
break
}
}
if !alreadyWaiting {
meta.Waiters = append(meta.Waiters, holder)
}
metaStr, err := encodeSlotMeta(meta)
if err != nil {
return fmt.Errorf("failed to encode slot metadata: %w", err)
}
if err := tx.UpdateIssue(ctx, slot.ID, map[string]interface{}{"metadata": metaStr}, actor); err != nil {
return fmt.Errorf("failed to add to waiters: %w", err)
}
result.Waiting = true
result.Position = len(meta.Waiters)
}
return nil
}
// Slot is available — acquire it atomically.
newMeta := slotMeta{Holder: holder, Waiters: meta.Waiters}
metaStr, err := encodeSlotMeta(newMeta)
if err != nil {
return fmt.Errorf("failed to encode slot metadata: %w", err)
}
if err := tx.UpdateIssue(ctx, slot.ID, map[string]interface{}{
"status": types.StatusInProgress,
"metadata": metaStr,
}, actor); err != nil {
return fmt.Errorf("failed to acquire slot: %w", err)View on GitHub (pinned to 71377f2769)
Solutions
- Retry MergeSlotAcquire — the transaction is atomic, so retry is safe
- Verify the slot exists with 'bd merge-slot create' / bd show of the slot ID
- Check database connectivity and lock contention (other long-running transactions)
- Inspect the wrapped error (%w) for the root cause from UpdateIssue
Defensive patterns
Strategy: retry
Validate before calling
if _, err := store.GetIssue(ctx, MergeSlotID(ctx, store)); err != nil || err == nil && slotNil { /* recreate slot */ } Try / catch
res, err := store.MergeSlotAcquire(ctx, holder, actor, true)
if err != nil && strings.Contains(err.Error(), "failed to add to waiters") {
return retryWithBackoff(func() error { _, err = store.MergeSlotAcquire(ctx, holder, actor, true); return err })
} Prevention
- Verify the merge-slot bead exists before acquiring ('bd merge-slot create' is idempotent)
- Keep database connections healthy; check Dolt server reachability under contention
- Avoid deleting the internal merge-slot bead during active merges
- Always inspect the wrapped cause, not just the wrapper message
When it happens
Trigger: MergeSlotAcquire with wait=true while the slot is held, and tx.UpdateIssue on the slot ID fails — e.g. database lock timeout, connection loss mid-transaction, the slot issue was deleted concurrently, or a storage-layer validation rejected the metadata string.
Common situations: Two agents contending for the merge slot on a slow or remote Dolt database; slot bead deleted or renamed by manual cleanup; transient DB outage during high-contention merges.
Related errors
- failed to acquire slot: %w
- failed to create digest issue: %w
- failed to link digest to root: %w
- failed to delete child %s: %w
- failed to close wisp root %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/16e2244cde43553b.
Report an issue: GitHub.