gastownhall/beads · error
failed to acquire slot: %w
Error message
failed to acquire slot: %w
What it means
This error wraps a failed tx.UpdateIssue that would have flipped the slot to StatusInProgress and written the new holder's metadata. The atomic check-and-set succeeded (slot was open) but the write failed, so the transaction rolls back and the slot remains free.
Source
Thrown at internal/storage/merge_slot.go:139
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)
}
result.Acquired = true
result.Holder = holder
return nil
},
)
if err != nil {
return nil, err
}
return &result, nil
}
// MergeSlotReleaseImpl is the shared implementation of Storage.MergeSlotRelease.
func MergeSlotReleaseImpl(ctx context.Context, s Storage, holder, actor string) error {
slotID := MergeSlotID(ctx, s)
return s.RunInTransaction(ctx,
fmt.Sprintf("bd: release merge slot %s", slotID),View on GitHub (pinned to 71377f2769)
Solutions
- Retry MergeSlotAcquire — the transaction guarantees atomicity so retrying is safe and race-free
- Check the wrapped error for the underlying UpdateIssue cause (lock timeout vs connection vs not-found)
- Recreate the slot if it was deleted: 'bd merge-slot create'
- Reduce contention or increase DB lock/transaction timeouts
Defensive patterns
Strategy: retry
Validate before calling
if _, err := store.GetIssue(ctx, MergeSlotID(ctx, store)); err != nil { return fmt.Errorf("slot missing: %w", err) } Try / catch
res, err := store.MergeSlotAcquire(ctx, holder, actor, false)
if err != nil && strings.Contains(err.Error(), "failed to acquire slot") {
// Safe to retry: the transaction rolled back, slot remains free.
return retryWithBackoff(func() error { _, err = store.MergeSlotAcquire(ctx, holder, actor, false); return err })
} Prevention
- Retry — transactional semantics make acquire idempotent and race-free
- Monitor DB lock timeouts if many agents contend for the slot
- Never delete the merge-slot bead while a merge queue is active
- Increase transaction/lock timeouts on slow remote Dolt deployments
When it happens
Trigger: MergeSlotAcquire on an open slot where tx.UpdateIssue on the slot ID fails: DB connection loss, lock timeout under contention (two acquirers racing, loser hits a write conflict), the slot bead was deleted between GetIssue and UpdateIssue, or a storage constraint/validation rejection.
Common situations: Racing agents acquiring the merge slot simultaneously on a busy Dolt database; network blip to a remote Dolt server; manual deletion of the merge-slot bead during an active merge queue.
Related errors
- failed to add to waiters: %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/188d46cda7824bcb.
Report an issue: GitHub.