ruvnet/ruflo · error · Error

Claim not found for issue: ${issueId}

Error message

Claim not found for issue: ${issueId}

What it means

Plain Error thrown by WorkStealingService.markStealable when repository.findByIssueId(issueId) returns null. Marking an issue stealable requires a live claim to attach steal metadata to. Note the inconsistency: the sibling steal() method returns a structured StealResult error for the same condition, but markStealable throws.

Source

Thrown at v3/@claude-flow/claims/src/application/work-stealing-service.ts:211

   * monotonic across the federation. Otherwise fall back to wall clock.
   */
  private nowMs(): number {
    if (this.hlc) return this.hlc.now().physicalMs;
    return Date.now();
  }

  // ===========================================================================
  // Mark Stealable
  // ===========================================================================

  /**
   * Mark work as stealable with the given reason
   */
  async markStealable(issueId: IssueId, info: StealableInfo): Promise<void> {
    const claim = await this.repository.findByIssueId(issueId);

    if (!claim) {
      throw new Error(`Claim not found for issue: ${issueId}`);
    }

    // Check if already stealable
    if (claim.stealInfo) {
      return; // Already marked
    }

    // Check grace period protection
    if (this.isInGracePeriod(claim)) {
      throw new Error(`Claim is still in grace period`);
    }

    // Check progress protection
    if (this.isProtectedByProgress(claim)) {
      throw new Error(`Claim is protected by progress (${claim.progress}%)`);
    }

    // Update claim with stealable info

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Confirm a claim exists (getStealable or a findByIssueId check) before marking.
  2. Skip ids without claims in auto-mark loops rather than throwing.
  3. Correct or prune the issueId list fed to the marker.
  4. Re-claim the issue if it should genuinely be stealable work.

Example fix

// before
await workStealing.markStealable(issueId, info); // throws

// after
const claim = await repo.findByIssueId(issueId);
if (claim) await workStealing.markStealable(issueId, info);
Defensive patterns

Strategy: validation

Validate before calling

const claim = await repository.findByIssueId(issueId);
if (!claim) return; // nothing to mark
await workStealing.markStealable(issueId, info);

Try / catch

try {
  await workStealing.markStealable(issueId, info);
} catch (e) {
  // plain Error; match on the known prefix
  if (e instanceof Error && /Claim not found for issue/.test(e.message)) return;
  throw e;
}

Prevention

When it happens

Trigger: Calling markStealable on an issue that was never claimed; after the claim was released/expired; an auto-marker scanning a list that includes unclaimed or released issue ids; wrong issueId.

Common situations: autoMarkStealable iterating over a broad id set that contains released issues; cross-store id mismatch; stale id list.

Related errors


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