ruvnet/ruflo · error · Error
Pool ${this.config.name} is at maximum capacity
Error message
Pool ${this.config.name} is at maximum capacity What it means
AgentPool caps the number of pooled agents at config.maxSize. add() throws when pooledAgents.size has already reached maxSize — the pool never silently grows past its configured bound. Slots become available again only through release(), which returns an agent to idle and may trigger scale-down via checkScaling().
Source
Thrown at v3/@claude-flow/swarm/src/agent-pool.ts:154
return;
}
this.busy.delete(agentId);
this.available.add(agentId);
pooled.acquiredAt = undefined;
pooled.lastUsed = new Date();
pooled.agent.status = 'idle';
pooled.agent.currentTask = undefined;
this.emit('agent.released', { agentId });
// Check if we need to scale down
await this.checkScaling();
}
async add(agent: AgentState): Promise<void> {
if (this.pooledAgents.size >= this.config.maxSize) {
throw new Error(`Pool ${this.config.name} is at maximum capacity`);
}
const pooled: PooledAgent = {
agent,
lastUsed: new Date(),
usageCount: 0,
};
this.pooledAgents.set(agent.id.id, pooled);
this.available.add(agent.id.id);
this.emit('agent.added', { agentId: agent.id.id });
}
async remove(agentId: string): Promise<void> {
const pooled = this.pooledAgents.get(agentId);
if (!pooled) {
return;View on GitHub (pinned to fa13ee4ad6)
Solutions
- Release agents when their work finishes: call pool.release(agentId) in try/finally.
- Increase config.maxSize to match the maximum number of concurrent agents.
- Before add(), compare current pool occupancy against maxSize and drain idle agents first.
- Diagnose leaks: 'agent.added' events should be balanced by 'agent.released'; use lastUsed/usageCount stats to find holders.
Example fix
// before — agents added but never released; pool pins at maxSize
await pool.add(agent);
await runTask(agent);
// after — release in finally and size the cap for peak concurrency
const pool = new AgentPool({ name: 'workers', maxSize: peakConcurrency });
await pool.add(agent);
try {
await runTask(agent);
} finally {
await pool.release(agent.id.id);
} Defensive patterns
Strategy: try-catch
Validate before calling
// track occupancy yourself: every add must pair with a release
let inPool = 0;
await pool.add(agent); inPool++;
try {
await runTask(agent);
} finally {
await pool.release(agent.id.id);
inPool--;
}
// check inPool < config.maxSize before the next add Try / catch
try {
await pool.add(agent);
} catch (e) {
if (e instanceof Error && e.message.endsWith('is at maximum capacity')) {
await drainIdleOrWaitForRelease(); // or rebuild the pool with a larger maxSize
} else {
throw e;
}
} Prevention
- Pair every add/acquire with release() in a finally block.
- Set maxSize for worst-case concurrent agents, not average load.
- Alert when occupancy pins at maxSize — it indicates a release leak or an undersized cap.
When it happens
Trigger: Calling add() while the pool already holds maxSize agents; agents acquired for work but never release()d (leak); an auto-scaler spawning new agents into a full pool; maxSize configured below the number of concurrently needed agents.
Common situations: Missing release() in a finally block after task execution; long-lived idle agents occupying slots; pool sizing never revisited after traffic grew; scale-up loop ignoring pool capacity.
Related errors
- Agent at maximum concurrent task capacity
- Max sessions (${this.config.maxSessions}) reached
- task step ${step.stepId} requires config.agentId or workflow
- agent_execute failed
- Agent ${this.id} is not available (status: ${this.status})
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/12b5753a2d81b5fa.
Report an issue: GitHub.