ruvnet/ruflo · error
Maximum agents (${this.config.maxAgents}) reached
Error message
Maximum agents (${this.config.maxAgents}) reached What it means
registerAgent() enforces the coordinator-level maxAgents ceiling: once state.agents.size reaches config.maxAgents, further registrations throw before an agent id is minted. This limit is independent of the TopologyManager maxAgents, so in a unified setup both limits apply and the lower one wins.
Source
Thrown at v3/@claude-flow/swarm/src/unified-coordinator.ts:305
if (this.state.status !== 'paused') {
return;
}
this.startBackgroundProcesses();
this.state.status = 'running';
this.emitEvent('swarm.resumed', { swarmId: this.state.id.id });
}
// ===== AGENT MANAGEMENT =====
async registerAgent(
agentData: Omit<AgentState, 'id'>
): Promise<string> {
const startTime = performance.now();
if (this.state.agents.size >= this.config.maxAgents) {
throw new Error(`Maximum agents (${this.config.maxAgents}) reached`);
}
this.agentCounter++;
const agentId: AgentId = {
id: `agent_${this.state.id.id}_${this.agentCounter}`,
swarmId: this.state.id.id,
type: agentData.type,
instance: this.agentCounter,
};
const agent: AgentState = {
...agentData,
id: agentId,
lastHeartbeat: new Date(),
connections: [],
};
// Add to stateView on GitHub (pinned to fa13ee4ad6)
Solutions
- Raise maxAgents in the UnifiedSwarmCoordinator config to cover the whole fleet
- Terminate or deregister idle/terminated agents before registering new ones
- Pre-check with getAllAgents().length against config.maxAgents and shed load instead of throwing
Example fix
// before
const coordinator = new UnifiedSwarmCoordinator({ ...baseConfig, maxAgents: 8 });
await Promise.all(agents.map(a => coordinator.registerAgent(a))); // throws at the 9th
// after
const coordinator = new UnifiedSwarmCoordinator({ ...baseConfig, maxAgents: agents.length + 4 });
await Promise.all(agents.map(a => coordinator.registerAgent(a))); Defensive patterns
Strategy: validation
Validate before calling
const current = coordinator.getAllAgents();
if (current.length >= config.maxAgents) {
const idle = current.filter(a => a.status === 'idle');
await terminateIdleAgents(idle); // free slots before scaling up
}
const agentId = await coordinator.registerAgent(agentData); Type guard
function hasAgentCapacity(coordinator: UnifiedSwarmCoordinator, maxAgents: number): boolean {
return coordinator.getAllAgents().length < maxAgents;
} Try / catch
try {
await coordinator.registerAgent(agentData);
} catch (err) {
if (err instanceof Error && err.message.includes('Maximum agents')) {
await terminateIdleAgents(coordinator.getAllAgents().filter(a => a.status === 'idle'));
return coordinator.registerAgent(agentData);
}
throw err;
} Prevention
- Set coordinator maxAgents and topology maxAgents together; the lower one wins
- Reap terminated agents from state.agents on shutdown paths
- Autoscalers should read getAllAgents().length before deciding to spawn
When it happens
Trigger: registerAgent() calls exceeding config.maxAgents; autoscaling that registers without tracking the current count; agent entries that were never deregistered accumulating in state.agents.
Common situations: Raising only the topology maxAgents but not the coordinator config; long-lived swarms retaining terminated agents in state.agents; test suites sharing one coordinator instance.
Related errors
- Maximum agents (${this.config.maxAgents}) reached
- Maximum tasks (${this.config.maxTasks}) reached
- Max sessions (${this.config.maxSessions}) reached
- Worker ${this.id} at capacity (${maxTasks} tasks)
- Pool ${this.id} at maximum capacity (${this.config.maxWorker
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/f35ec083b3e05d9c.
Report an issue: GitHub.