ruvnet/ruflo · error · Error
No pending handoff for issue ${issueId}
Error message
No pending handoff for issue ${issueId} What it means
acceptHandoff(issueId, claimant) requires a claim in status 'handoff-pending'. If no claim exists or its status is anything else (active, blocked, completed, etc.), it throws 'No pending handoff for issue ...'. The handoff is not accepted and no claimant change occurs.
Source
Thrown at v3/@claude-flow/cli/src/services/claim-service.ts:358
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> {
const claim = this.claims.get(issueId);
if (!claim || claim.status !== 'handoff-pending') {
throw new Error(`No pending handoff for issue ${issueId}`);
}
if (!claim.handoffTo || !this.isSameClaimant(claim.handoffTo, claimant)) {
throw new Error(`Handoff not addressed to ${this.formatClaimant(claimant)}`);
}
const previousClaimant = claim.claimant;
claim.claimant = claimant;
claim.status = 'active';
claim.statusChangedAt = new Date();
delete claim.handoffTo;
delete claim.handoffReason;
await this.saveClaims();
this.emitEvent({
type: 'issue:handoff:accepted',
timestamp: new Date(),
issueId,View on GitHub (pinned to 6b01dc5a68)
Solutions
- Only call acceptHandoff in response to an issue:handoff:requested event you actually received.
- Make accept idempotent: catch 'No pending handoff' and verify the claim is already in the desired state before treating as error.
- Use a correlation id so duplicate accepts are deduped upstream.
Example fix
// before: blind retry
await claims.acceptHandoff(issueId, me); // throws on second attempt
// after: idempotent accept
try {
await claims.acceptHandoff(issueId, me);
} catch (e) {
if (!String(e.message).includes('No pending handoff')) throw e;
// verify we already hold it; if so, success
} Defensive patterns
Strategy: try-catch
Try / catch
try {
await claims.acceptHandoff(issueId, claimant);
} catch (e) {
if (String(e.message).includes('No pending handoff')) {
// verify we already hold it; if so, treat as success
return;
}
throw e;
} Prevention
- Only accept in response to a real issue:handoff:requested event.
- Make accept idempotent in retry paths by catching 'No pending handoff'.
- Use correlation ids so duplicate accepts are deduped upstream.
When it happens
Trigger: Calling acceptHandoff before requestHandoff was called; calling it after the handoff was already accepted/rejected/cancelled; calling it on an issue whose handoff timed out and reverted to active; double-accept.
Common situations: Network retries that re-deliver an accept after the first succeeded; race between accept and reject; UI accepting a handoff that was concurrently cancelled.
Related errors
- Issue ${issueId} is not claimed
- HANDOFF_PENDING
- Issue ${issueId} is not claimed by ${this.formatClaimant(cla
- Issue ${issueId} is not claimed by ${this.formatClaimant(fro
- Handoff not addressed to ${this.formatClaimant(claimant)}
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/407e5f63e94b4269.
Report an issue: GitHub.