ruvnet/ruflo · error
Issue is not claimed by
Error message
Issue ${issueId} is not claimed by ${this.formatClaimant(from)} What it means
ClaimService.requestHandoff(issueId, from, to, reason) found a claim for the issue, but the stored claimant does not match the from argument (isSameClaimant fails). Only the current owner can initiate a handoff — this prevents an agent from volunteering someone else's work. The message names the from claimant that was rejected.
Solutions
- Read the current owner first (getIssueStatus(issueId).claimant) and pass that as from
- Have the owning worker itself call requestHandoff rather than a third party
- Stabilize agent identity (persistent agentId) so restarts do not change ownership mid-flight
Example fix
// before
await claims.requestHandoff(issueId, coordinator, workerB, 'rebalance'); // coordinator is not the owner
// after
const claim = await claims.getIssueStatus(issueId);
if (!claim) throw new Error('nothing to hand off');
await claims.requestHandoff(issueId, claim.claimant, workerB, 'rebalance'); Defensive patterns
Strategy: try-catch
Validate before calling
const claim = await claims.getIssueStatus(issueId);
if (!claim) throw new Error('nothing to hand off');
await claims.requestHandoff(issueId, claim.claimant, to, reason); // from = actual owner Try / catch
try {
await claims.requestHandoff(issueId, from, to, reason);
} catch (e) {
if (e instanceof Error && e.message.includes('is not claimed by')) {
const c = await claims.getIssueStatus(issueId);
if (c) await claims.requestHandoff(issueId, c.claimant, to, reason); // retry as the real owner
else throw e;
} else throw e;
} Prevention
- Always read the current owner (getIssueStatus) instead of assuming who holds the claim
- Let the owning worker initiate its own handoff; coordinators should request, not forge, the from identity
- Keep agent identity durable across restarts to keep isSameClaimant meaningful
When it happens
Trigger: Passing a supervisor/coordinator Claimant as from when a worker actually holds the claim, using a stale agentId after the worker restarted with a new identity, or calling requestHandoff with swapped from/to arguments.
Common situations: Coordinator-driven reassignment code that assumes it can hand off on behalf of workers, agent ids regenerated per session, argument-order mistakes in the four-parameter call.
Related errors
- Handoff not addressed to
- Issue is not claimed by
- Issue is not claimed by
- No pending handoff for issue
- UNAUTHORIZED
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/08e3c2638f0e5eab.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/services/claim-service.ts:337
}
// ==========================================================================
// Handoffs
// ==========================================================================
async requestHandoff(
issueId: string,
from: Claimant,
to: Claimant,
reason: string
): Promise<void> {
const claim = this.claims.get(issueId);
if (!claim) {
throw new Error(`Issue ${issueId} is not claimed`);
}
if (!this.isSameClaimant(claim.claimant, from)) {
throw new Error(`Issue ${issueId} is not claimed by ${this.formatClaimant(from)}`);
}
claim.status = 'handoff-pending';
claim.statusChangedAt = new Date();
claim.handoffTo = to;
claim.handoffReason = reason;
await this.saveClaims();
this.emitEvent({
type: 'issue:handoff:requested',
timestamp: new Date(),
issueId,
claimant: from,
data: { to, reason },
});
}
async acceptHandoff(issueId: string, claimant: Claimant): Promise<void> {View on GitHub (pinned to fa13ee4ad6)