{"record":{"id":"58e862ce4b583302","repo":"gastownhall/beads","slug":"failed-to-resolve-claimable-statuses-w","errorCode":null,"errorMessage":"failed to resolve claimable statuses: %w","messagePattern":"failed to resolve claimable statuses: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/claim.go","lineNumber":67,"sourceCode":"\t\treturn nil, fmt.Errorf(\"failed to get issue for claim: %w\", err)\n\t}\n\n\tnow := time.Now().UTC()\n\n\t// Rewrite row_lock with the claim (see lease.go): a concurrent reclaim or\n\t// close on the same row is forced to conflict rather than silently\n\t// cell-merge. The lease itself is granted separately below, in the\n\t// ephemeral leases table — claims commit (status/assignee are\n\t// history-worthy) but lease grants and heartbeats do not (bd-lrgn1).\n\trowLockClause, rowLockArgs := RowLockClause()\n\n\t// An issue is claimable from \"open\" plus any configured custom status whose\n\t// category is \"active\" (e.g. a draft->ready->in_progress lifecycle where\n\t// \"ready\" should be claimable). WIP/done/frozen customs are excluded so the\n\t// anti-steal protection from GH-3570 is preserved.\n\tclaimableStatuses, err := ClaimableSourceStatusesInTx(ctx, tx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to resolve claimable statuses: %w\", err)\n\t}\n\tstatusPlaceholders, statusArgs := buildSQLInClause(claimableStatuses)\n\n\t// Pool-aware claim (bd-bguz6): a dispatcher may pre-assign issues to a\n\t// pool pseudo-assignee (e.g. \"fable-crew\"). Aliases listed in the\n\t// claim.pools config are claimable by any actor through the same CAS;\n\t// issues assigned to a real actor keep their anti-steal protection.\n\tpools, err := ClaimPoolAliasesInTx(ctx, tx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to resolve claim pools: %w\", err)\n\t}\n\n\t// Claimability of the assignee slot, judged in Go against oldIssue (the\n\t// pre-image read above, inside this same transaction) rather than as a\n\t// spelling-sensitive SQL predicate (ga-v2k49, same shape as ga-5ksp5's\n\t// unclaim.go fix): empty/unassigned, already this actor — including an\n\t// idempotent re-claim spelled under a different layer's separator\n\t// convention (ga-wzl83) — or assigned to a claim-pool alias. That last","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/claim.go#L49-L85","documentation":"Before claiming, ClaimIssueInTx resolves which statuses are claimable ('open' plus configured custom statuses whose category is 'active') via ClaimableSourceStatusesInTx; failure is wrapped as \"failed to resolve claimable statuses: %w\". This keeps custom-status lifecycle configs (e.g. draft->ready->in_progress) claim-aware while preserving anti-steal protection. The error means reading the status configuration from the DB failed.","triggerScenarios":"Calling claim paths when: the custom-status config storage is missing/corrupt, the transaction is dead, the context is cancelled, or the SELECT over configured statuses fails.","commonSituations":"Databases created before custom-status support (missing config table); a hand-edited or corrupt status configuration; transient DB failures during dispatcher claim loops.","solutions":["Migrate the database so custom-status configuration storage exists.","Retry the claim; resolution failures from connectivity are transient.","Inspect the wrapped error for 'no such table' and repair/upgrade the schema (bd doctor).","Validate custom status config (bd doctor / config check) after manual edits."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if err := bdDoctor(); err != nil { return fmt.Errorf(\"schema/config problem: %w\", err) }","typeGuard":null,"tryCatchPattern":"if err != nil {\n    tx.Rollback()\n    return retry(fmt.Errorf(\"claimable status resolution failed: %w\", err))\n}","preventionTips":["Upgrade/migrate bd so custom-status config storage exists.","Validate custom status configuration after manual edits (bd doctor).","Retry transient failures in dispatcher claim loops with backoff.","Do not hand-edit status config tables directly."],"tags":["database","claim","status","configuration"],"backgroundTag":"config-resolution-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}