ruvnet/ruflo · error
Issue is not claimed by
Error message
Issue ${issueId} is not claimed by ${this.formatClaimant(claimant)} What it means
ClaimService.release(issueId, claimant) found a claim for the issue, but the stored claimant does not match the claimant argument (compared via isSameClaimant). Ownership is enforced on release so a random agent cannot free another agent's claim; only the holder (or an explicit steal/handoff flow) can change claim state. The message names the caller that attempted the release.
Solutions
- Release with the exact same Claimant (agentId + type) that acquired the claim — persist the claimant used at claim() time
- If a different agent must take over, use the steal/handoff flows (markStealable/steal, requestHandoff) instead of release()
- Inspect the stored claim via getIssueStatus(issueId).claimant to see who actually owns it
Example fix
// before
await claims.release(issueId, { agentId: 'coordinator', type: 'coordinator' }); // not the owner -> throws
// after
const claim = await claims.getIssueStatus(issueId);
if (!claim) return;
await claims.release(issueId, claim.claimant); // release as the recorded owner Defensive patterns
Strategy: try-catch
Validate before calling
const claim = await claims.getIssueStatus(issueId);
if (claim && isSameClaimant(claim.claimant, me)) {
await claims.release(issueId, me);
} Try / catch
try {
await claims.release(issueId, me);
} catch (e) {
if (e instanceof Error && e.message.includes('is not claimed by')) {
// not the owner: read claim.claimant via getIssueStatus and either act as that claimant or use the steal/handoff flow
} else throw e;
} Prevention
- Persist the exact Claimant used at claim() time and reuse it for release()
- Give agents stable, persisted agentIds so restarts preserve ownership
- For taking over someone else's claim use the steal/handoff APIs, never release()
When it happens
Trigger: Releasing with a Claimant whose agentId/type differs from the one used in claim() — e.g. a restarted worker got a new agentId, a typo'd or default claimant, or a supervisor trying release() instead of the steal API.
Common situations: Agent identity not persisted across restarts so the 'same' worker returns with a different id, copy-pasted cleanup code using the coordinator's Claimant instead of the worker's, tests reusing one Claimant object for multiple roles.
Related errors
- Handoff not addressed to
- Issue is not claimed by
- UNAUTHORIZED
- Issue is not claimed by
- Issue is not claimed
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/824cf393bfa60381.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/services/claim-service.ts:306
this.emitEvent({
type: 'issue:claimed',
timestamp: now,
issueId,
claimant,
previousClaimant: existing?.claimant,
});
return { success: true, claim };
}
async release(issueId: string, claimant: Claimant): Promise<void> {
const claim = this.claims.get(issueId);
if (!claim) {
throw new Error(`Issue ${issueId} is not claimed`);
}
if (!this.isSameClaimant(claim.claimant, claimant)) {
throw new Error(`Issue ${issueId} is not claimed by ${this.formatClaimant(claimant)}`);
}
this.claims.delete(issueId);
this.stealableInfo.delete(issueId);
await this.saveClaims();
this.emitEvent({
type: 'issue:released',
timestamp: new Date(),
issueId,
claimant,
});
}
// ==========================================================================
// Handoffs
// ==========================================================================
View on GitHub (pinned to fa13ee4ad6)