ruvnet/ruflo · error
No nodes available for leader election
Error message
No nodes available for leader election
What it means
electLeader() requires at least one node in state.nodes; on an empty topology it throws before any election strategy runs. The fast paths (hierarchical queen lookup, centralized coordinator) also cannot produce a leader without nodes. This is a bootstrap-ordering guard, not a transient failure.
Source
Thrown at v3/@claude-flow/swarm/src/topology-manager.ts:196
if (updates.status !== undefined) node.status = updates.status;
if (updates.connections !== undefined) {
node.connections = updates.connections;
this.adjacencyList.set(agentId, new Set(updates.connections));
}
if (updates.metadata !== undefined) {
node.metadata = { ...node.metadata, ...updates.metadata };
}
this.emit('node.updated', { agentId, updates });
}
getLeader(): string | undefined {
return this.state.leader;
}
async electLeader(): Promise<string> {
if (this.state.nodes.length === 0) {
throw new Error('No nodes available for leader election');
}
// For hierarchical topology, the queen is the leader (O(1) lookup)
if (this.config.type === 'hierarchical') {
const queen = this.queenNode;
if (queen) {
this.state.leader = queen.agentId;
return queen.agentId;
}
}
// For centralized topology, the coordinator is the leader (O(1) lookup)
if (this.config.type === 'centralized') {
const coordinator = this.coordinatorNode;
if (coordinator) {
this.state.leader = coordinator.agentId;
return coordinator.agentId;
}View on GitHub (pinned to fa13ee4ad6)
Solutions
- addNode() at least one node before electLeader()
- Guard the call: skip election while getState().nodes.length is 0
- Re-check swarm size after mass removals before triggering re-election
Example fix
// before
const topology = new TopologyManager(config);
await topology.electLeader(); // throws: no nodes
// after
await topology.addNode('queen-1', 'queen');
await topology.electLeader(); Defensive patterns
Strategy: validation
Validate before calling
function hasNodes(topology: TopologyManager): boolean {
return topology.getState().nodes.length > 0;
}
if (hasNodes(topology)) {
await topology.electLeader();
} else {
// defer election until the first node joins
topology.once('node.added', () => topology.electLeader());
} Try / catch
try {
await topology.electLeader();
} catch (err) {
if (err instanceof Error && err.message === 'No nodes available for leader election') {
await waitForFirstJoin(topology); // bootstrap race: retry once after a join
return topology.electLeader();
}
throw err;
} Prevention
- Sequence startup as initialize, then addNode, then electLeader; never elect inside initialize
- Skip re-election when the swarm empties after node.removed events
- Seed at least one node in test setup before election assertions
When it happens
Trigger: Calling electLeader() before any addNode(); calling it again after removeNode() drained the swarm; tests that tear down all nodes and then assert a new leader.
Common situations: Election triggered in startup hooks before agents join; shrinking a swarm to zero then re-electing; unit tests constructing a TopologyManager and immediately electing.
Related errors
- Only primary can propose values
- Only leader can propose values
- Node ${agentId} already exists in topology
- Maximum agents (${this.config.maxAgents}) reached
- Node ${agentId} not found
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/a7ce4ce82a939107.
Report an issue: GitHub.