{"record":{"id":"abdf8a092a2cc0b0","repo":"ruvnet/ruflo","slug":"agent-at-maximum-concurrent-task-capacity","errorCode":null,"errorMessage":"Agent at maximum concurrent task capacity","messagePattern":"Agent at maximum concurrent task capacity","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/swarm/src/domain/entities/agent.ts","lineNumber":253,"sourceCode":"   */\n  recover(): void {\n    if (this._status !== 'error') {\n      throw new Error('Can only recover from error state');\n    }\n    this._status = 'idle';\n    delete this._metadata['lastError'];\n    this._updatedAt = new Date();\n  }\n\n  /**\n   * Assign a task to this agent\n   */\n  assignTask(taskId: string): void {\n    if (this._status === 'terminated') {\n      throw new Error('Cannot assign task to terminated agent');\n    }\n    if (this._currentTaskIds.size >= this._maxConcurrentTasks) {\n      throw new Error('Agent at maximum concurrent task capacity');\n    }\n\n    this._currentTaskIds.add(taskId);\n    this._status = 'busy';\n    this._lastActiveAt = new Date();\n    this._updatedAt = new Date();\n  }\n\n  /**\n   * Complete a task\n   */\n  completeTask(taskId: string): void {\n    if (!this._currentTaskIds.has(taskId)) {\n      throw new Error(`Task ${taskId} not assigned to this agent`);\n    }\n\n    this._currentTaskIds.delete(taskId);\n    this._completedTaskCount++;","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/swarm/src/domain/entities/agent.ts#L235-L271","documentation":"assignTask() enforces maxConcurrentTasks: it throws when the size of the agent's current task-id set already equals the configured cap. The entity deliberately fails fast instead of queueing — overflow handling is the caller's responsibility.","triggerScenarios":"Assigning N+1 tasks to an agent whose maxConcurrentTasks is N (default caps are small in this domain layer)\nLeaked task ids: completeTask()/fail paths never ran, so the set stays full (ghost tasks)\nCoordinator fan-out that ignores per-agent capacity when balancing maxConcurrentTasks configured to a lower value than the dispatcher's parallelism","commonSituations":"Static round-robin dispatchers hitting the cap before any task completes Tasks stuck in 'running' whose completion callback was lost, permanently consuming a slot\nMerging workloads that raised task counts without raising maxConcurrentTasks Tests creating agents with maxConcurrentTasks: 1 then assigning two tasks","solutions":["Always pair assignment with completion: call completeTask(taskId) (or the task's fail path) in a finally so slots free up","Check available capacity before assigning (see validation snippet) or expose canAcceptTask() in your layer","Raise maxConcurrentTasks on agent creation to match the dispatcher's parallelism","Scale horizontally: pick a different agent or spawn one when all are at capacity"],"exampleFix":"// before\nagent.assignTask(task.id); // throws when full\n\n// after\nfunction tryAssign(agent, taskId) {\n  if (agent.status === 'terminated') return false;\n  if (agent.currentTaskCount >= agent.maxConcurrentTasks) return false; // or track via your repo\n  agent.assignTask(taskId);\n  return true;\n}\n// creation: new Agent(..., { maxConcurrentTasks: 8 }) to match dispatcher","handlingStrategy":"validation","validationCode":"// Track assignments in the dispatcher and enforce the cap before calling the entity:\nconst inflight = dispatcher.countInflight(agent.id);\nif (inflight >= agentMax) { agent = pickAnother() || spawnAgent(); }\nagent.assignTask(taskId);","typeGuard":null,"tryCatchPattern":"try { agent.assignTask(taskId); }\ncatch (e) {\n  if (e instanceof Error && e.message === 'Agent at maximum concurrent task capacity') {\n    return enqueueOrReassign(taskId); // backpressure: queue the task / pick another agent\n  }\n  throw e;\n}","preventionTips":["Always release slots: call completeTask(taskId) in a finally block on every code path","Size maxConcurrentTasks to the dispatcher's parallelism at agent creation","Free leaked slots: monitor agents whose currentTaskCount stays at max for long periods (ghost tasks)"],"tags":["agent","task-assignment","capacity","backpressure","typescript"],"backgroundTag":"resource-capacity-exceeded","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}