{"record":{"id":"8fb7aed95fd88075","repo":"ruvnet/ruflo","slug":"agent-id-already-exists","errorCode":null,"errorMessage":"Agent ${id} already exists","messagePattern":"Agent (.+?) already exists","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugins/src/integrations/agentic-flow.ts","lineNumber":227,"sourceCode":"  // Agent Management\n  // =========================================================================\n\n  /**\n   * Spawn a new agent.\n   */\n  async spawnAgent(options: AgentSpawnOptions): Promise<SpawnedAgent> {\n    if (!this.swarmInitialized) {\n      throw new Error('Swarm not initialized');\n    }\n\n    if (this.agents.size >= (this.config.maxConcurrentAgents ?? 15)) {\n      throw new Error(`Maximum agent limit (${this.config.maxConcurrentAgents}) reached`);\n    }\n\n    const id = options.id ?? `agent-${this.nextAgentId++}`;\n\n    if (this.agents.has(id)) {\n      throw new Error(`Agent ${id} already exists`);\n    }\n\n    const agent: SpawnedAgent = {\n      id,\n      type: options.type,\n      status: 'active',\n      capabilities: options.capabilities ?? [],\n      parentId: options.parentId,\n      spawnedAt: new Date(),\n    };\n\n    this.agents.set(id, agent);\n\n    this.emit(AGENTIC_FLOW_EVENTS.AGENT_SPAWNED, {\n      agent,\n      timestamp: new Date(),\n    });\n","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugins/src/integrations/agentic-flow.ts#L209-L245","documentation":"spawnAgent() rejects duplicate ids: after resolving options.id (or generating agent-N), it checks agents.has(id) and throws on collision. Auto-generated ids cannot collide, so this only fires when you pass an explicit options.id that already exists — including ids of terminated agents, which stay in the map.","triggerScenarios":"Spawning with an explicit id already registered (active, idle, or terminated); deterministic id schemes like `${taskType}-worker` colliding on retry; two modules spawning agents with fixed names.","commonSituations":"Retry logic reusing the same id after a partial failure; parallel code paths assigning semantic agent names; resume-from-log implementations replaying spawn calls with recorded ids.","solutions":["Omit options.id and use the auto-generated agent-N ids","Track the ids you have spawned and skip or terminate-and-rename before reusing an explicit id","On retry, derive a fresh unique id (append an attempt counter or uuid suffix)"],"exampleFix":"// before\nawait flow.spawnAgent({ id: 'crawler', type: 'researcher' });\n// retry path later:\nawait flow.spawnAgent({ id: 'crawler', type: 'researcher' }); // Error: already exists\n\n// after\nawait flow.spawnAgent({ id: `crawler-${Date.now()}`, type: 'researcher' });\n// or simply omit id and capture the generated one:\nconst agent = await flow.spawnAgent({ type: 'researcher' });","handlingStrategy":"validation","validationCode":"const spawned = new Set<string>();\nasync function spawnUnique(opts: AgentSpawnOptions): Promise<SpawnedAgent> {\n  if (opts.id && spawned.has(opts.id)) {\n    throw new Error(`agent id ${opts.id} already spawned on this integration`);\n  }\n  const agent = await flow.spawnAgent(opts);\n  spawned.add(agent.id);\n  return agent;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit options.id unless determinism is required; auto ids cannot collide","Derive retry ids with an attempt suffix or uuid","Keep one Set of live agent ids per integration and consult it before explicit-id spawns"],"tags":["swarm","agents","duplicate-id","unique-constraints"],"backgroundTag":"duplicate-key","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}