ruvnet/ruflo · error · Error

Issue ${issueId} is not claimed by ${this.formatClaimant(fro

Error message

Issue ${issueId} is not claimed by ${this.formatClaimant(from)}

What it means

Second guard in requestHandoff(): the claim exists but its claimant is not isSameClaimant to `from`. The message names the caller's `from` claimant. This prevents an agent from initiating a handoff on behalf of a different (possibly unaware) claimant. Status is not changed to handoff-pending.

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 6b01dc5a68)

Solutions

  1. Look up the actual current claimant and pass it as `from`.
  2. Restrict requestHandoff to the holder calling it itself.
  3. Use stable identity fields (agentId/userId) consistently across claim, release, and handoff.

Example fix

// before: coordinator guesses `from`
await claims.requestHandoff(issueId, assumedFrom, to, reason); // throws

// after: derive from from current claim
const claim = claims.list?.().find(c => c.issueId === issueId);
if (!claim) return;
await claims.requestHandoff(issueId, claim.claimant, to, reason);
Defensive patterns

Strategy: validation

Validate before calling

function handoffFromCurrentHolder(claims, issueId, to, reason) {
  const c = claims.list?.().find(x => x.issueId === issueId);
  if (!c) throw new Error('no claim to hand off');
  return claims.requestHandoff(issueId, c.claimant, to, reason);
}

Prevention

When it happens

Trigger: Agent B calling requestHandoff with from=agentA on an issue held by agentB (or vice versa); a coordinator passing the wrong `from`; stale claimant identity after an agent rename.

Common situations: Coordinator-driven handoffs that guess the current holder; mixed human/agent workflows where the `from` type is wrong; copy-paste of a claimant object between calls.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/08e3c2638f0e5eab. Report an issue: GitHub.