{"record":{"id":"5df2a753ec777987","repo":"ruvnet/ruflo","slug":"issue-input-issueid-is-not-stealable-or-not-cla","errorCode":null,"errorMessage":"Issue ${input.issueId} is not stealable or not claimed","messagePattern":"Issue (.+?) is not stealable or not claimed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/claims/src/api/mcp-tools.ts","lineNumber":947,"sourceCode":"\n      // Update issue\n      const issue = issueStore.get(input.issueId);\n      if (issue) {\n        issue.claimedBy = input.stealerId;\n      }\n\n      return {\n        stolen: true,\n        issueId: input.issueId,\n        newClaimId,\n        previousClaimant,\n        contestWindowMs: 300000, // 5 minutes\n        stolenAt,\n      };\n    }\n  }\n\n  throw new Error(`Issue ${input.issueId} is not stealable or not claimed`);\n}\n\n/**\n * Get stealable issues\n */\nasync function handleIssueGetStealable(\n  input: z.infer<typeof issueGetStealableSchema>,\n  context?: ToolContext\n): Promise<{\n  issues: Array<{\n    issueId: string;\n    title: string;\n    priority: IssuePriority;\n    currentClaimant: string;\n    stealableReason?: string;\n  }>;\n  total: number;\n}> {","sourceCodeStart":929,"sourceCodeEnd":965,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/claims/src/api/mcp-tools.ts#L929-L965","documentation":"Thrown by the simple steal handler when no claim in claimStore matches the issue with claim.stealable === true. The steal flow requires the current holder to have first marked the claim stealable; otherwise the scan finds nothing and this fires.","triggerScenarios":"Calling steal on an issue that was never marked stealable, on an unclaimed issue, or after the stealable flag was cleared.","commonSituations":"Skipping the markStealable step; the stealable window expired; another agent already stole it (clearing the flag); typo in issueId.","solutions":["Call markStealable first (by the current holder), then steal.","Re-check the issue's stealable state before stealing to handle races.","If the issue is unclaimed, use claim directly rather than steal."],"exampleFix":"// before\nawait steal.handler({ issueId, claimantId: 'bob' }); // throws 72 — not marked stealable\n\n// after\nawait markStealable.handler({ issueId, claimantId: currentHolderId, reason: 'handoff' });\nawait steal.handler({ issueId, claimantId: 'bob' });","handlingStrategy":"validation","validationCode":"function isStealable(store, issueId) {\n  for (const c of store.values()) {\n    if (c.issueId === issueId && c.stealable === true) return true;\n  }\n  return false;\n}","typeGuard":"null","tryCatchPattern":"try { await steal.handler(input, ctx); } catch (e) { if (/not stealable/.test(e.message)) { /* mark or skip */ } else throw e; }","preventionTips":["Always run markStealable before steal.","Re-check the stealable flag right before stealing to lose races cleanly."],"tags":["claims","mcp","workflow","state-machine","typescript"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}