{"record":{"id":"7a3ec24cf8c5f162","repo":"ruvnet/ruflo","slug":"no-eligible-peers-for-exploration","errorCode":null,"errorMessage":"no eligible peers for exploration","messagePattern":"no eligible peers for exploration","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/browser/src/application/mcts-explorer.ts","lineNumber":88,"sourceCode":"    this.peers = options.peers;\n    this.scorer = options.scorer;\n    this.maxDepth = options.maxDepth ?? 5;\n    this.maxBranches = options.maxBranches ?? 32;\n    this.defaultPeerBudgetUsd = options.defaultPeerBudgetUsd ?? 1.0;\n    this.ucb = options.ucb ?? { c: Math.SQRT2 };\n    this.trustedPublicKeys = options.trustedPublicKeys ?? [];\n  }\n\n  /** Explore from a seed root action. Returns the winning branch's ID + aggregate stats. */\n  async explore(input: {\n    rootAction: RootAction;\n    goal: string;\n    expansionPolicy: ExpansionPolicy;\n  }): Promise<MctsRunResult> {\n    const runId = 'run-' + Date.now() + '-' + randomBytes(3).toString('hex');\n    const rootId = 'br-root-' + randomBytes(3).toString('hex');\n    const rootPeer = this.pickPeer();\n    if (!rootPeer) throw new Error('no eligible peers for exploration');\n\n    const root: McTsBranch = McTsBranchSchema.parse({\n      id: rootId,\n      runId,\n      parentId: null,\n      peerId: rootPeer.id,\n      action: input.rootAction.action,\n      input: input.rootAction.input,\n      depth: 0,\n      visits: 0,\n      totalValue: 0,\n      status: 'pending',\n      costUsd: 0,\n      createdAt: new Date().toISOString(),\n    });\n    this.branches.set(rootId, root);\n\n    // Execute and expand iteratively. Counter is # of EXECUTIONS (not # of","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/browser/src/application/mcts-explorer.ts#L70-L106","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst explorer = new MctsExplorer({ peers: [] , ...opts });\nawait explorer.explore({ rootAction, goal, expansionPolicy }); // throws\n\n// after\nconst explorer = new MctsExplorer({ peers: [localPeer, remotePeer], ...opts });\nif (!explorer.peers.some(p => !explorer.peerBlacklist.has(p.id))) {\n  throw new Error('configure healthy peers before exploration');\n}\nawait explorer.explore({ rootAction, goal, expansionPolicy });","handlingStrategy":"validation","validationCode":"const eligible = explorer.peers.filter(p => !explorer.peerBlacklist.has(p.id));\nif (eligible.length === 0) {\n  throw new Error('MCTS explore aborted: all peers blacklisted or none configured');\n}\nawait explorer.explore({ rootAction, goal, expansionPolicy });","typeGuard":"const hasEligiblePeer = (x: { peers: PeerAdapter[]; peerBlacklist: Set<string> }): boolean =>\n  x.peers.some(p => !x.peerBlacklist.has(p.id));","tryCatchPattern":"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; }","preventionTips":["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"],"tags":["mcts","peers","distributed-exploration","blacklist"],"backgroundTag":"no-available-resources","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}