ruvnet/ruflo · error

No active claim found for issue

Error message

No active claim found for issue ${input.issueId} by ${input.claimantId}

What it means

Thrown by the issue status-update handler in @claude-flow/claims when no claim in claimStore matches both input.issueId and input.claimantId with an active status. The handler iterates claims looking for the caller's active claim before applying status/progress/notes updates, and throws after the loop finds nothing.

Solutions

  1. (Re-)claim the issue with the same claimantId before sending status updates
  2. Verify an active claim exists for (issueId, claimantId) before each update batch
  3. If the claim was stolen or released, stop updating and restart the task lifecycle from claim
  4. Use identical claimantId/claimantType values across claim and update calls (store them from the claim response)

Example fix

// before
await statusTool({ issueId, claimantId: 'agent-1', status: 'in_progress' }); // never claimed

// after
await claimTool({ issueId, claimantId: 'agent-1', claimantType: 'agent' });
await statusTool({ issueId, claimantId: 'agent-1', status: 'in_progress' });
Defensive patterns

Strategy: validation

Validate before calling

const claim = await getClaimTool({ issueId });
if (!claim || claim.claimantId !== claimantId || claim.status !== 'active') {
  await claimTool({ issueId, claimantId, claimantType });
}
await statusTool({ issueId, claimantId, status, progress });

Try / catch

try { await statusTool(input); } catch (e) { if (e instanceof Error && e.message.startsWith('No active claim found')) { await claimTool({ issueId: input.issueId, claimantId: input.claimantId, claimantType }); return statusTool(input); } throw e; }

Prevention

When it happens

Trigger: Calling the status-update tool before ever claiming the issue; calling it after the claim was released or expired; using a claimantId that differs from the one on the existing claim (including claimantType mismatch in the lookup); store restart losing the claim records.

Common situations: Worker restarts that resume progress reporting without re-claiming; agents whose claims were stolen mid-task still posting updates; inconsistent claimant id formatting between claim and update calls.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/5cd2dfdf4c7f42cd. Report an issue: GitHub.

Appendix: 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 fa13ee4ad6)