ruvnet/ruflo · error
no eligible peers for exploration
Error message
no eligible peers for exploration
What it means
Thrown by MctsExplorer.explore in @claude-flow/browser when pickPeer() cannot find any peer adapter to run the root (or child) branch. pickPeer() filters this.peers against this.peerBlacklist and returns null when the eligible list is empty, so the error means either zero peers were configured or every peer has been blacklisted (typically after failures).
Solutions
- Ensure at least one non-blacklisted PeerAdapter is passed in the MctsExplorer options.peers array before calling explore()
- Inspect/clear peerBlacklist for peers that have recovered (re-enable or re-register them) before starting a new run
- Add redundancy: configure multiple peers so a single blacklisted peer does not empty the eligible set
- Pre-check eligibility before exploring (peers.some(p => !blacklist.has(p.id))) and surface a clearer configuration error
Example fix
// before
const explorer = new MctsExplorer({ peers: [] , ...opts });
await explorer.explore({ rootAction, goal, expansionPolicy }); // throws
// after
const explorer = new MctsExplorer({ peers: [localPeer, remotePeer], ...opts });
if (!explorer.peers.some(p => !explorer.peerBlacklist.has(p.id))) {
throw new Error('configure healthy peers before exploration');
}
await explorer.explore({ rootAction, goal, expansionPolicy }); Defensive patterns
Strategy: validation
Validate before calling
const eligible = explorer.peers.filter(p => !explorer.peerBlacklist.has(p.id));
if (eligible.length === 0) {
throw new Error('MCTS explore aborted: all peers blacklisted or none configured');
}
await explorer.explore({ rootAction, goal, expansionPolicy }); Type guard
const hasEligiblePeer = (x: { peers: PeerAdapter[]; peerBlacklist: Set<string> }): boolean =>
x.peers.some(p => !x.peerBlacklist.has(p.id)); Try / catch
try { await explorer.explore(input); } catch (e) { if (e instanceof Error && e.message === 'no eligible peers for exploration') { /* clear blacklist for recovered peers or register new peers */ } throw e; } Prevention
- Register at least two PeerAdapters so one blacklisted peer cannot empty the pool
- Monitor blacklist growth during long runs and re-enable recovered peers
- Fail fast at construction if options.peers is empty
When it happens
Trigger: Constructing MctsExplorer with an empty peers array and calling explore(); or all configured peers having been added to peerBlacklist (e.g. after repeated execution failures) so eligible.filter(p => !peerBlacklist.has(p.id)) yields nothing at the root branch creation.
Common situations: Running MCTS exploration in a single-node setup with no peer adapters registered; peers going unhealthy mid-run and getting blacklisted, then a subsequent explore() call failing immediately; forgetting to re-register recovered peers after an outage.
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/7a3ec24cf8c5f162.
Report an issue: GitHub.
Appendix: 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 # ofView on GitHub (pinned to fa13ee4ad6)