{"record":{"id":"31dafa610a8ce70f","repo":"gastownhall/beads","slug":"merge-slot-not-found-s-run-bd-merge-slot-creat-31dafa","errorCode":null,"errorMessage":"merge slot not found: %s (run 'bd merge-slot create' first)","messagePattern":"merge slot not found: (.+?) \\(run 'bd merge-slot create' first\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/merge_slot.go","lineNumber":97,"sourceCode":"\n// MergeSlotAcquireImpl is the shared implementation of Storage.MergeSlotAcquire.\n// It uses RunInTransaction to ensure atomic check-and-set, preventing two\n// agents from simultaneously acquiring the slot.\nfunc MergeSlotAcquireImpl(ctx context.Context, s Storage, holder, actor string, wait bool) (*MergeSlotResult, error) {\n\tif holder == \"\" {\n\t\treturn nil, fmt.Errorf(\"merge-slot acquire: holder must not be empty\")\n\t}\n\n\tslotID := MergeSlotID(ctx, s)\n\tvar result MergeSlotResult\n\tresult.SlotID = slotID\n\n\terr := s.RunInTransaction(ctx,\n\t\tfmt.Sprintf(\"bd: acquire merge slot %s for %s\", slotID, holder),\n\t\tfunc(tx Transaction) error {\n\t\t\tslot, err := tx.GetIssue(ctx, slotID)\n\t\t\tif err != nil || slot == nil {\n\t\t\t\treturn fmt.Errorf(\"merge slot not found: %s (run 'bd merge-slot create' first)\", slotID)\n\t\t\t}\n\n\t\t\tmeta := parseSlotMeta(slot)\n\t\t\tresult.Holder = meta.Holder\n\n\t\t\tif slot.Status != types.StatusOpen {\n\t\t\t\t// Slot is held.\n\t\t\t\tif wait {\n\t\t\t\t\talreadyWaiting := false\n\t\t\t\t\tfor _, w := range meta.Waiters {\n\t\t\t\t\t\tif w == holder {\n\t\t\t\t\t\t\talreadyWaiting = true\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif !alreadyWaiting {\n\t\t\t\t\t\tmeta.Waiters = append(meta.Waiters, holder)\n\t\t\t\t\t}","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/merge_slot.go#L79-L115","documentation":"Inside the acquire transaction, MergeSlotAcquireImpl fetches the slot bead; if GetIssue errors or returns nil, the tx returns this error and the acquire aborts. Unlike MergeSlotCheckImpl's wrapped variant, this is the plain (non-%w) form used inside the transaction closure — same root cause: the slot bead does not exist under the ID derived from issue_prefix.","triggerScenarios":"Calling MergeSlotAcquire before the slot was ever created, after the slot bead was deleted, or after an issue_prefix change moved MergeSlotID to a nonexistent ID; also when the underlying GetIssue inside RunInTransaction fails (connection/tx error) — the code cannot distinguish and reports not-found.","commonSituations":"Fresh repo where 'bd merge-slot create' was skipped; prefix renamed so agents look for bd-merge-slot while the actual bead is gt-merge-slot; slot bead deleted during a cleanup sweep that didn't know it was infrastructure.","solutions":["Run 'bd merge-slot create' first (idempotent), then retry the acquire","Check issue_prefix config consistency across agents — all must derive the same slot ID","Search the store for '<prefix>-merge-slot' or 'gt:slot' labeled beads to find a slot under an old prefix and recreate/migrate it","If GetIssue is actually failing (not missing), inspect DB connectivity and tx health in the wrapped error from RunInTransaction"],"exampleFix":"// before\nres, err := store.MergeSlotAcquire(ctx, holder, actor, true) // fails: no slot\n// after\nif _, err := store.MergeSlotCreate(ctx, actor); err != nil { return err } // idempotent\nres, err := store.MergeSlotAcquire(ctx, holder, actor, true)","handlingStrategy":"fallback","validationCode":"// ensure slot exists before acquiring (idempotent)\nif _, err := store.MergeSlotCreate(ctx, actor); err != nil { return err }","typeGuard":"func slotReady(ctx context.Context, s storage.Storage) bool {\n\tslot, err := s.GetIssue(ctx, storage.MergeSlotID(ctx, s))\n\treturn err == nil && slot != nil\n}","tryCatchPattern":"res, err := store.MergeSlotAcquire(ctx, holder, actor, wait)\nif err != nil && strings.Contains(err.Error(), \"merge slot not found\") {\n\tif _, cerr := store.MergeSlotCreate(ctx, actor); cerr != nil { return cerr }\n\tres, err = store.MergeSlotAcquire(ctx, holder, actor, wait)\n}","preventionTips":["Bootstrap 'bd merge-slot create' before any acquire attempts","Align issue_prefix across all agents so everyone derives the same slot ID","Exclude gt:slot-labeled infrastructure beads from deletion/cleanup tooling","Create the slot in a setup step of CI pipelines before parallel merge jobs run"],"tags":["merge-queue","not-found","setup"],"backgroundTag":"merge-slot-not-found","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}