{"record":{"id":"5cd2dfdf4c7f42cd","repo":"ruvnet/ruflo","slug":"no-active-claim-found-for-issue-input-issueid-b","errorCode":null,"errorMessage":"No active claim found for issue ${input.issueId} by ${input.claimantId}","messagePattern":"No active claim found for issue (.+?) by (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/claims/src/api/mcp-tools.ts","lineNumber":676,"sourceCode":"  // Simple implementation\n  for (const claim of claimStore.values()) {\n    if (claim.issueId === input.issueId && claim.claimantId === input.claimantId) {\n      claim.status = input.status;\n      claim.lastActivityAt = new Date().toISOString();\n      if (input.progress !== undefined) {\n        claim.metadata = { ...claim.metadata, progress: input.progress };\n      }\n      return {\n        issueId: input.issueId,\n        status: input.status,\n        progress: input.progress,\n        updatedAt: claim.lastActivityAt,\n        notes: input.notes,\n      };\n    }\n  }\n\n  throw new Error(`No active claim found for issue ${input.issueId} by ${input.claimantId}`);\n}\n\n/**\n * List unclaimed issues\n */\nasync function handleIssueListAvailable(\n  input: z.infer<typeof issueListAvailableSchema>,\n  context?: ToolContext\n): Promise<{\n  issues: Issue[];\n  total: number;\n  limit: number;\n  offset: number;\n}> {\n  initializeMockData();\n\n  if (context?.claimsService) {\n    const result = await context.claimsService.listAvailableIssues(input);","sourceCodeStart":658,"sourceCodeEnd":694,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/claims/src/api/mcp-tools.ts#L658-L694","documentation":"Thrown by the simple updateStatus handler after it iterates claimStore.values() looking for an active claim matching both issueId and claimantId, and finds none. The handler updates progress/notes on a claim that must exist and belong to the caller; absence means either no claim was ever made or it belongs to someone else.","triggerScenarios":"Calling updateStatus before claimIssue; calling it with a claimantId that does not own the claim; calling after the claim was released (status no longer active).","commonSituations":"Agent reporting progress on an issue it never claimed; status update racing with a release; stale claimantId after a restart.","solutions":["Ensure claimIssue succeeded for this issueId + claimantId before updateStatus.","Re-claim if the previous claim was released or expired.","List the claimant's active claims first and skip the update if none match."],"exampleFix":"// before\nawait updateStatus.handler({ issueId, claimantId: 'alice', status: 'in-progress', progress: 50 }); // throws 70\n\n// after\nconst claim = [...claimStore.values()].find(c => c.issueId === issueId && c.claimantId === 'alice' && c.status === 'active');\nif (claim) await updateStatus.handler({ issueId, claimantId: 'alice', status: 'in-progress', progress: 50 });","handlingStrategy":"validation","validationCode":"function hasActiveClaim(store, issueId, claimantId) {\n  for (const c of store.values()) {\n    if (c.issueId === issueId && c.claimantId === claimantId && c.status === 'active') return true;\n  }\n  return false;\n}","typeGuard":"null","tryCatchPattern":"try { await updateStatus.handler(input, ctx); } catch (e) { if (/No active claim/.test(e.message)) { /* re-claim or skip */ } else throw e; }","preventionTips":["Claim before reporting progress.","Re-claim after a restart if the prior claim lapsed."],"tags":["claims","mcp","ownership","missing-record","typescript"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}