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

  1. Read the current owner first (getIssueStatus(issueId).claimant) and pass that as from
  2. Have the owning worker itself call requestHandoff rather than a third party
  3. 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

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


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)