{"record":{"id":"824cf393bfa60381","repo":"ruvnet/ruflo","slug":"issue-issueid-is-not-claimed-by-this-formatcl","errorCode":null,"errorMessage":"Issue ${issueId} is not claimed by ${this.formatClaimant(claimant)}","messagePattern":"Issue (.+?) is not claimed by (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/services/claim-service.ts","lineNumber":306,"sourceCode":"    this.emitEvent({\n      type: 'issue:claimed',\n      timestamp: now,\n      issueId,\n      claimant,\n      previousClaimant: existing?.claimant,\n    });\n\n    return { success: true, claim };\n  }\n\n  async release(issueId: string, claimant: Claimant): Promise<void> {\n    const claim = this.claims.get(issueId);\n    if (!claim) {\n      throw new Error(`Issue ${issueId} is not claimed`);\n    }\n\n    if (!this.isSameClaimant(claim.claimant, claimant)) {\n      throw new Error(`Issue ${issueId} is not claimed by ${this.formatClaimant(claimant)}`);\n    }\n\n    this.claims.delete(issueId);\n    this.stealableInfo.delete(issueId);\n    await this.saveClaims();\n\n    this.emitEvent({\n      type: 'issue:released',\n      timestamp: new Date(),\n      issueId,\n      claimant,\n    });\n  }\n\n  // ==========================================================================\n  // Handoffs\n  // ==========================================================================\n","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/services/claim-service.ts#L288-L324","documentation":"ClaimService.release(issueId, claimant) found a claim for the issue, but the stored claimant does not match the claimant argument (compared via isSameClaimant). Ownership is enforced on release so a random agent cannot free another agent's claim; only the holder (or an explicit steal/handoff flow) can change claim state. The message names the caller that attempted the release.","triggerScenarios":"Releasing with a Claimant whose agentId/type differs from the one used in claim() — e.g. a restarted worker got a new agentId, a typo'd or default claimant, or a supervisor trying release() instead of the steal API.","commonSituations":"Agent identity not persisted across restarts so the 'same' worker returns with a different id, copy-pasted cleanup code using the coordinator's Claimant instead of the worker's, tests reusing one Claimant object for multiple roles.","solutions":["Release with the exact same Claimant (agentId + type) that acquired the claim — persist the claimant used at claim() time","If a different agent must take over, use the steal/handoff flows (markStealable/steal, requestHandoff) instead of release()","Inspect the stored claim via getIssueStatus(issueId).claimant to see who actually owns it"],"exampleFix":"// before\nawait claims.release(issueId, { agentId: 'coordinator', type: 'coordinator' }); // not the owner -> throws\n\n// after\nconst claim = await claims.getIssueStatus(issueId);\nif (!claim) return;\nawait claims.release(issueId, claim.claimant); // release as the recorded owner","handlingStrategy":"try-catch","validationCode":"const claim = await claims.getIssueStatus(issueId);\nif (claim && isSameClaimant(claim.claimant, me)) {\n  await claims.release(issueId, me);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await claims.release(issueId, me);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('is not claimed by')) {\n    // not the owner: read claim.claimant via getIssueStatus and either act as that claimant or use the steal/handoff flow\n  } else throw e;\n}","preventionTips":["Persist the exact Claimant used at claim() time and reuse it for release()","Give agents stable, persisted agentIds so restarts preserve ownership","For taking over someone else's claim use the steal/handoff APIs, never release()"],"tags":["claim-service","ownership","release","authorization"],"backgroundTag":"ownership-mismatch","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}