gastownhall/beads · error

merge-slot create: %w

Error message

merge-slot create: %w

What it means

MergeSlotCreateImpl creates the canonical merge-slot bead (id <prefix>-merge-slot) via s.CreateIssue, after an idempotent existence check. This error wraps any CreateIssue failure — e.g. a validation rejection, an ID conflict, or a database error — so the merge slot could not be created.

Source

Thrown at internal/storage/merge_slot.go:54

// MergeSlotCreateImpl is the shared implementation of Storage.MergeSlotCreate.
func MergeSlotCreateImpl(ctx context.Context, s Storage, actor string) (*types.Issue, error) {
	slotID := MergeSlotID(ctx, s)

	// Idempotent: return existing slot without error.
	if existing, err := s.GetIssue(ctx, slotID); err == nil && existing != nil {
		return existing, nil
	}

	issue := &types.Issue{
		ID:          slotID,
		Title:       "Merge Slot",
		Description: "Exclusive access slot for serialized conflict resolution in the merge queue.",
		IssueType:   types.TypeTask,
		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{

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the command — MergeSlotCreateImpl is idempotent; a transient race usually resolves on retry
  2. Check the wrapped CreateIssue error for duplicate-ID vs validation cause and address specifically
  3. Verify the issue_prefix config is stable and correct (MergeSlotID derives the slot ID from it)
  4. Inspect store health (connectivity, read-only flags, Dolt logs) if the underlying write failed

Example fix

// before
slot, err := store.MergeSlotCreate(ctx, actor)
if err != nil { return err } // hard-fails on transient race
// after
slot, err := store.MergeSlotCreate(ctx, actor)
if err != nil {
	// idempotent op — safe to retry once
	slot, err = store.MergeSlotCreate(ctx, actor)
	if err != nil { return fmt.Errorf("merge-slot create failed: %w", err) }
}
Defensive patterns

Strategy: retry

Validate before calling

// idempotent create: safe to call regardless
if _, err := store.MergeSlotCheck(ctx); err == nil {
	// slot already exists — skip create
}

Try / catch

slot, err := store.MergeSlotCreate(ctx, actor)
if err != nil {
	// creation is idempotent — one retry absorbs create races
	if slot, err = store.MergeSlotCreate(ctx, actor); err != nil {
		return fmt.Errorf("merge-slot create: %w", err)
	}
}

Prevention

When it happens

Trigger: Calling MergeSlotCreate (bd merge-slot create) when CreateIssue fails: the slot ID already exists but a concurrent create raced past the GetIssue check, the issue fails validation, the issue_prefix config changed producing a different slot ID, or the underlying store errors (connection, read-only DB, constraint).

Common situations: Two agents racing to create the slot simultaneously; issue_prefix reconfigured between the existence check and create; Dolt write failure or replication conflict; store in read-only/maintenance mode.

Related errors


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