gastownhall/beads · warning

merge slot not found: %s (run 'bd merge-slot create' first):

Error message

merge slot not found: %s (run 'bd merge-slot create' first): %w

What it means

MergeSlotCheckImpl looks up the canonical slot bead (<prefix>-merge-slot) via GetIssue; if the lookup errors or returns nil, it returns this sentinel error wrapping ErrNotFound. It simply means the merge slot has never been created in this store (or the issue_prefix changed so the expected ID no longer matches).

Source

Thrown at internal/storage/merge_slot.go:68

		Status:      types.StatusOpen,
		Priority:    0,
	}
	if err := s.CreateIssue(ctx, issue, actor); err != nil {
		return nil, fmt.Errorf("merge-slot create: %w", err)
	}
	if err := s.AddLabel(ctx, slotID, mergeSlotLabel, actor); err != nil {
		// Non-fatal: label is cosmetic.
		_ = err
	}
	return s.GetIssue(ctx, slotID)
}

// MergeSlotCheckImpl is the shared implementation of Storage.MergeSlotCheck.
func MergeSlotCheckImpl(ctx context.Context, s Storage) (*MergeSlotStatus, error) {
	slotID := MergeSlotID(ctx, s)
	slot, err := s.GetIssue(ctx, slotID)
	if err != nil || slot == nil {
		return nil, fmt.Errorf("merge slot not found: %s (run 'bd merge-slot create' first): %w",
			slotID, ErrNotFound)
	}
	meta := parseSlotMeta(slot)
	return &MergeSlotStatus{
		SlotID:    slotID,
		Available: slot.Status == types.StatusOpen,
		Holder:    meta.Holder,
		Waiters:   meta.Waiters,
	}, nil
}

// MergeSlotAcquireImpl is the shared implementation of Storage.MergeSlotAcquire.
// It uses RunInTransaction to ensure atomic check-and-set, preventing two
// agents from simultaneously acquiring the slot.
func MergeSlotAcquireImpl(ctx context.Context, s Storage, holder, actor string, wait bool) (*MergeSlotResult, error) {
	if holder == "" {
		return nil, fmt.Errorf("merge-slot acquire: holder must not be empty")
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run 'bd merge-slot create' to create the slot — the error message tells you exactly this
  2. Check the issue_prefix config; if it changed, either update it back or create the slot under the new prefix
  3. Look for an orphaned '<oldprefix>-merge-slot' bead and migrate/relabel it if you want to preserve history
  4. Verify you are pointed at the intended database (right .beads dir / Dolt remote)

Example fix

// before
status, err := store.MergeSlotCheck(ctx)
if err != nil { return err } // not found on fresh repo
// after
slot, err := store.MergeSlotCreate(ctx, actor) // idempotent; creates if missing
if err != nil { return err }
status, err := store.MergeSlotCheck(ctx)
Defensive patterns

Strategy: fallback

Validate before calling

// probe cheaply before reading status
slotID := "bd-merge-slot" // or derive from prefix
if _, err := store.GetIssue(ctx, slotID); err != nil {
	_, _ = store.MergeSlotCreate(ctx, actor) // create-if-missing
}

Type guard

func mergeSlotExists(ctx context.Context, s storage.Storage) bool {
	slot, err := s.GetIssue(ctx, storage.MergeSlotID(ctx, s))
	return err == nil && slot != nil
}

Try / catch

status, err := store.MergeSlotCheck(ctx)
if err != nil && strings.Contains(err.Error(), "merge slot not found") {
	if _, err := store.MergeSlotCreate(ctx, actor); err != nil { return err }
	status, err = store.MergeSlotCheck(ctx)
}

Prevention

When it happens

Trigger: Calling MergeSlotCheck (bd merge-slot status) before ever running 'bd merge-slot create' in this repo, or after issue_prefix config changed so MergeSlotID now points at a different, nonexistent bead ID.

Common situations: Fresh clone/brand-new database where the slot was never created; team renamed the prefix (e.g. gt → bd) so old slot beads are orphaned under a different ID; slot bead accidentally deleted.

Related errors


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