{"record":{"id":"8d320e7e044581b2","repo":"ruvnet/ruflo","slug":"issue-input-issueid-is-not-claimed-by-input-c","errorCode":null,"errorMessage":"Issue ${input.issueId} is not claimed by ${input.claimantId}","messagePattern":"Issue (.+?) is not claimed by (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/claims/src/api/mcp-tools.ts","lineNumber":568,"sourceCode":"}> {\n  if (context?.claimsService) {\n    const result = await context.claimsService.releaseClaim(input);\n    return {\n      released: result.released,\n      issueId: input.issueId,\n      releasedAt: result.releasedAt,\n      reason: input.reason,\n    };\n  }\n\n  // Simple implementation\n  const issue = issueStore.get(input.issueId);\n  if (!issue) {\n    throw new Error(`Issue not found: ${input.issueId}`);\n  }\n\n  if (issue.claimedBy !== input.claimantId) {\n    throw new Error(`Issue ${input.issueId} is not claimed by ${input.claimantId}`);\n  }\n\n  // Find and update the claim\n  for (const claim of claimStore.values()) {\n    if (claim.issueId === input.issueId && claim.claimantId === input.claimantId) {\n      claim.status = 'released';\n      claim.lastActivityAt = new Date().toISOString();\n    }\n  }\n\n  issue.claimedBy = undefined;\n\n  return {\n    released: true,\n    issueId: input.issueId,\n    releasedAt: new Date().toISOString(),\n    reason: input.reason,\n  };","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/claims/src/api/mcp-tools.ts#L550-L586","documentation":"Thrown by the simple releaseClaim handler when the issue exists and is claimed, but issue.claimedBy !== input.claimantId. The release path requires the caller to be the current holder; any other claimant (including an admin) is rejected at this layer.","triggerScenarios":"A claimant other than the holder calling release; the holder's ID changed between claim and release (e.g., new agent instance ID); a stale claimantId passed by mistake.","commonSituations":"An agent restart assigned a new ID but tried to release the old ID's claim; a coordinator trying to release on behalf of a worker without using the handoff flow; copy-paste of the wrong claimant ID.","solutions":["Pass the exact claimantId that holds the claim (the value in issue.claimedBy).","If you need to transfer, use requestHandoff rather than release+claim.","For administrative release, use a privileged service method rather than this MCP handler."],"exampleFix":"// before\nawait releaseClaim.handler({ issueId, claimantId: 'agent-v2' }); // throws 69, holder is 'agent-v1'\n\n// after\nconst issue = issueStore.get(issueId);\nawait releaseClaim.handler({ issueId, claimantId: issue.claimedBy });","handlingStrategy":"validation","validationCode":"function isHolder(issue, claimantId) { return !!issue && issue.claimedBy === claimantId; }\nif (!isHolder(issueStore.get(input.issueId), input.claimantId)) throw new Error('not the holder');","typeGuard":"function isHolder(issue, id) { return !!issue && issue.claimedBy === id; }","tryCatchPattern":"null","preventionTips":["Pass the exact claimantId stored in issue.claimedBy.","Use requestHandoff for ownership transfer rather than release+claim."],"tags":["claims","mcp","authorization","ownership","typescript"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}