ruvnet/ruflo · error
Issue is not claimed by
Error message
Issue ${input.issueId} is not claimed by ${input.claimantId} What it means
Thrown by the release-claim MCP tool handler when the issue exists and is claimed, but issue.claimedBy !== input.claimantId — the caller is not the owner of the claim. This protects against one agent releasing another agent's active claim; note the comparison is on the claimant id string, so type/namespace mismatches (agent:1 vs 1) also trip it.
Solutions
- Release with the exact claimantId recorded in claim.claimantId (inspect the claim first)
- If ownership legitimately moved, complete the handoff flow so the new owner releases it
- If the owner is dead, use the steal flow to acquire the claim, then release it as the new owner
Example fix
// before
await releaseTool({ issueId, claimantId: 'agent-orchestrator' }); // claim held by 'agent-worker-1'
// after
const claim = await getClaimTool({ issueId });
await releaseTool({ issueId, claimantId: claim.claimantId }); // release as the recorded owner Defensive patterns
Strategy: validation
Validate before calling
const issue = await getIssueTool({ issueId });
if (issue.claimedBy !== claimantId) {
throw new Error(`cannot release: claim held by ${issue.claimedBy}`);
}
await releaseTool({ issueId, claimantId }); Try / catch
try { await releaseTool(input); } catch (e) { if (e instanceof Error && e.message.includes('is not claimed by')) { /* fetch real owner and escalate */ } throw e; } Prevention
- Always release with the exact claimantId returned from the claim call
- Store claimantId alongside the task so shutdown code uses the right identity
When it happens
Trigger: Calling release with a claimantId different from the one used at claim time; using 'agent:coder-1' as claimantId when the claim was stored under 'coder-1'; supervisors attempting to force-release on behalf of a worker without matching ids.
Common situations: Handoff flows where ownership moved to a new agent but the old owner still calls release; id-format drift between subsystems; well-intentioned orchestrators cleaning up worker claims with their own id.
Related errors
- UNAUTHORIZED
- Handoff not addressed to
- Issue is already claimed by
- Issue is not stealable or not claimed
- Issue is not claimed by
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/8d320e7e044581b2.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/claims/src/api/mcp-tools.ts:568
}> {
if (context?.claimsService) {
const result = await context.claimsService.releaseClaim(input);
return {
released: result.released,
issueId: input.issueId,
releasedAt: result.releasedAt,
reason: input.reason,
};
}
// Simple implementation
const issue = issueStore.get(input.issueId);
if (!issue) {
throw new Error(`Issue not found: ${input.issueId}`);
}
if (issue.claimedBy !== input.claimantId) {
throw new Error(`Issue ${input.issueId} is not claimed by ${input.claimantId}`);
}
// Find and update the claim
for (const claim of claimStore.values()) {
if (claim.issueId === input.issueId && claim.claimantId === input.claimantId) {
claim.status = 'released';
claim.lastActivityAt = new Date().toISOString();
}
}
issue.claimedBy = undefined;
return {
released: true,
issueId: input.issueId,
releasedAt: new Date().toISOString(),
reason: input.reason,
};View on GitHub (pinned to fa13ee4ad6)