ruvnet/ruflo · error · Error

no eligible peers for exploration

Error message

no eligible peers for exploration

What it means

Thrown by MctsExplorer.explore() at the very start of a run when pickPeer() returns null. pickPeer filters peers against the peerBlacklist set, so this fires when every peer passed to the constructor has since been blacklisted. The constructor already rejects an empty peers array with a different message, so this specific error means peers existed at construction but none are now eligible (budget exhausted, bad signatures, or a prior run poisoned the explorer's mutable state).

Source

Thrown at v3/@claude-flow/browser/src/application/mcts-explorer.ts:88

    this.peers = options.peers;
    this.scorer = options.scorer;
    this.maxDepth = options.maxDepth ?? 5;
    this.maxBranches = options.maxBranches ?? 32;
    this.defaultPeerBudgetUsd = options.defaultPeerBudgetUsd ?? 1.0;
    this.ucb = options.ucb ?? { c: Math.SQRT2 };
    this.trustedPublicKeys = options.trustedPublicKeys ?? [];
  }

  /** Explore from a seed root action. Returns the winning branch's ID + aggregate stats. */
  async explore(input: {
    rootAction: RootAction;
    goal: string;
    expansionPolicy: ExpansionPolicy;
  }): Promise<MctsRunResult> {
    const runId = 'run-' + Date.now() + '-' + randomBytes(3).toString('hex');
    const rootId = 'br-root-' + randomBytes(3).toString('hex');
    const rootPeer = this.pickPeer();
    if (!rootPeer) throw new Error('no eligible peers for exploration');

    const root: McTsBranch = McTsBranchSchema.parse({
      id: rootId,
      runId,
      parentId: null,
      peerId: rootPeer.id,
      action: input.rootAction.action,
      input: input.rootAction.input,
      depth: 0,
      visits: 0,
      totalValue: 0,
      status: 'pending',
      costUsd: 0,
      createdAt: new Date().toISOString(),
    });
    this.branches.set(rootId, root);

    // Execute and expand iteratively. Counter is # of EXECUTIONS (not # of

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Construct a fresh MctsExplorer (new MctsExplorer(options)) for each explore() call so blacklist/spend state does not leak between runs.
  2. Before exploring, verify options.peers has length > 0 and that at least one peer has budgetUsd > 0 (or defaultPeerBudgetUsd > 0).
  3. If using trustedPublicKeys, ensure every peer signs with a key in that list; otherwise leave trustedPublicKeys unset to accept any valid signature.
  4. Raise defaultPeerBudgetUsd or each peer's budgetUsd so a single run cannot exhaust all peers.

Example fix

// before
const explorer = new MctsExplorer({ peers, scorer });
await explorer.explore({ rootAction, goal, expansionPolicy });
await explorer.explore({ rootAction: another, goal, expansionPolicy }); // throws 60

// after — fresh explorer per run
function runMcts(peers, scorer, input) {
  const explorer = new MctsExplorer({ peers, scorer });
  return explorer.explore(input);
}
Defensive patterns

Strategy: validation

Validate before calling

function hasEligiblePeer(opts) {
  return Array.isArray(opts.peers)
    && opts.peers.length > 0
    && opts.peers.some(p => (p.budgetUsd ?? opts.defaultPeerBudgetUsd ?? 1.0) > 0);
}
// before explore:
if (!hasEligiblePeer(options)) throw new Error('configure at least one peer with positive budget');

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Calling explorer.explore() on an explorer instance that has already completed a run where every peer was blacklisted (budget exhausted or invalid trajectory signatures). Also fired when constructing the explorer with peers whose budgetUsd is 0, or when reusing a single MctsExplorer instance across runs because peerBlacklist, peerSpend, and peerSignatureBlacklist are instance fields that accumulate across explore() calls.

Common situations: Sharing one MctsExplorer across many runs without realizing the blacklist is never cleared; setting defaultPeerBudgetUsd to 0; a federation where all peers return Ed25519 signatures not in trustedPublicKeys (so they get signature-blacklisted after the first call).

Related errors


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