ruvnet/ruflo · error · Error
No active claim found for issue ${input.issueId} by ${input.
Error message
No active claim found for issue ${input.issueId} by ${input.claimantId} What it means
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.
Source
Thrown at v3/@claude-flow/claims/src/api/mcp-tools.ts:676
// Simple implementation
for (const claim of claimStore.values()) {
if (claim.issueId === input.issueId && claim.claimantId === input.claimantId) {
claim.status = input.status;
claim.lastActivityAt = new Date().toISOString();
if (input.progress !== undefined) {
claim.metadata = { ...claim.metadata, progress: input.progress };
}
return {
issueId: input.issueId,
status: input.status,
progress: input.progress,
updatedAt: claim.lastActivityAt,
notes: input.notes,
};
}
}
throw new Error(`No active claim found for issue ${input.issueId} by ${input.claimantId}`);
}
/**
* List unclaimed issues
*/
async function handleIssueListAvailable(
input: z.infer<typeof issueListAvailableSchema>,
context?: ToolContext
): Promise<{
issues: Issue[];
total: number;
limit: number;
offset: number;
}> {
initializeMockData();
if (context?.claimsService) {
const result = await context.claimsService.listAvailableIssues(input);View on GitHub (pinned to 6b01dc5a68)
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.
Example fix
// before
await updateStatus.handler({ issueId, claimantId: 'alice', status: 'in-progress', progress: 50 }); // throws 70
// after
const claim = [...claimStore.values()].find(c => c.issueId === issueId && c.claimantId === 'alice' && c.status === 'active');
if (claim) await updateStatus.handler({ issueId, claimantId: 'alice', status: 'in-progress', progress: 50 }); Defensive patterns
Strategy: validation
Validate before calling
function hasActiveClaim(store, issueId, claimantId) {
for (const c of store.values()) {
if (c.issueId === issueId && c.claimantId === claimantId && c.status === 'active') return true;
}
return false;
} Type guard
null
Try / catch
try { await updateStatus.handler(input, ctx); } catch (e) { if (/No active claim/.test(e.message)) { /* re-claim or skip */ } else throw e; } Prevention
- Claim before reporting progress.
- Re-claim after a restart if the prior claim lapsed.
When it happens
Trigger: 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).
Common situations: Agent reporting progress on an issue it never claimed; status update racing with a release; stale claimantId after a restart.
Related errors
- Issue not found: ${input.issueId}
- Issue ${input.issueId} is not claimed by ${input.claimantId}
- Issue ${input.issueId} is already claimed by ${issue.claimed
- Issue ${input.issueId} is not stealable or not claimed
- UNAUTHORIZED
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/5cd2dfdf4c7f42cd.
Report an issue: GitHub.