ruvnet/ruflo · error · Error

MctsExplorer requires at least one peer

Error message

MctsExplorer requires at least one peer

What it means

Constructor guard in MctsExplorer: it refuses to build an explorer whose options.peers is an empty array. The Monte-Carlo Tree Search exploration requires at least one peer to expand/roll out branches against, and the rest of the options (maxDepth, maxBranches, ucb.c, defaultPeerBudgetUsd, trustedPublicKeys) all default sensibly, but peers has no default and cannot be empty.

Source

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

  trajectoryEnvelope: unknown,
) => Promise<RootAction[]>;

export class MctsExplorer {
  private readonly peers: PeerAdapter[];
  private readonly scorer: ValueScorer;
  private readonly maxDepth: number;
  private readonly maxBranches: number;
  private readonly defaultPeerBudgetUsd: number;
  private readonly ucb: UcbParams;
  private readonly trustedPublicKeys: string[];

  private branches: Map<string, McTsBranch> = new Map();
  private peerSpend: Map<string, number> = new Map();
  private peerBlacklist: Set<string> = new Set();
  private peerSignatureBlacklist: Set<string> = new Set();

  constructor(options: MctsExplorerOptions) {
    if (options.peers.length === 0) throw new Error('MctsExplorer requires at least one peer');
    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();

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Ensure options.peers has at least one entry before constructing the explorer; gate construction on peers.length > 0.
  2. Run peer discovery/trust filtering after, not before, you have a non-empty candidate set.
  3. If zero peers is a legitimate runtime state, skip constructing the explorer (return null / a no-op explorer) rather than passing [].
  4. Add a config validation step that fails fast with a clearer message when the peers source is empty.

Example fix

// before
const explorer = new MctsExplorer({ peers: filteredPeers, scorer }); // throws if filteredPeers=[]
// after
if (filteredPeers.length === 0) {
  throw new Error("no trusted peers available after filtering; cannot run MCTS exploration");
}
const explorer = new MctsExplorer({ peers: filteredPeers, scorer });
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(peers) || peers.length === 0) {
  throw new Error("MctsExplorer needs >=1 peer; got 0");
}
return new MctsExplorer({ peers, scorer });

Type guard

function isNonEmptyPeerList(x: unknown): x is unknown[] {
  return Array.isArray(x) && x.length > 0;
}

Prevention

When it happens

Trigger: new MctsExplorer({ peers: [], ... }) — e.g. the peer list was filtered down to zero by peerBlacklist/signature checks before construction, or a config loader returned an empty peers array.

Common situations: Initialising the explorer before the peer-discovery/allowlist step has populated peers; a config/env var that lists peers being unset; all configured peers failing a trust/public-key filter upstream so the array handed to the constructor is empty.

Related errors


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