ruvnet/ruflo · error

Agent ${id} already exists

Error message

Agent ${id} already exists

What it means

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.

Source

Thrown at v3/@claude-flow/plugins/src/integrations/agentic-flow.ts:227

  // Agent Management
  // =========================================================================

  /**
   * Spawn a new agent.
   */
  async spawnAgent(options: AgentSpawnOptions): Promise<SpawnedAgent> {
    if (!this.swarmInitialized) {
      throw new Error('Swarm not initialized');
    }

    if (this.agents.size >= (this.config.maxConcurrentAgents ?? 15)) {
      throw new Error(`Maximum agent limit (${this.config.maxConcurrentAgents}) reached`);
    }

    const id = options.id ?? `agent-${this.nextAgentId++}`;

    if (this.agents.has(id)) {
      throw new Error(`Agent ${id} already exists`);
    }

    const agent: SpawnedAgent = {
      id,
      type: options.type,
      status: 'active',
      capabilities: options.capabilities ?? [],
      parentId: options.parentId,
      spawnedAt: new Date(),
    };

    this.agents.set(id, agent);

    this.emit(AGENTIC_FLOW_EVENTS.AGENT_SPAWNED, {
      agent,
      timestamp: new Date(),
    });

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Omit options.id and use the auto-generated agent-N ids
  2. Track the ids you have spawned and skip or terminate-and-rename before reusing an explicit id
  3. On retry, derive a fresh unique id (append an attempt counter or uuid suffix)

Example fix

// before
await flow.spawnAgent({ id: 'crawler', type: 'researcher' });
// retry path later:
await flow.spawnAgent({ id: 'crawler', type: 'researcher' }); // Error: already exists

// after
await flow.spawnAgent({ id: `crawler-${Date.now()}`, type: 'researcher' });
// or simply omit id and capture the generated one:
const agent = await flow.spawnAgent({ type: 'researcher' });
Defensive patterns

Strategy: validation

Validate before calling

const spawned = new Set<string>();
async function spawnUnique(opts: AgentSpawnOptions): Promise<SpawnedAgent> {
  if (opts.id && spawned.has(opts.id)) {
    throw new Error(`agent id ${opts.id} already spawned on this integration`);
  }
  const agent = await flow.spawnAgent(opts);
  spawned.add(agent.id);
  return agent;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/8fb7aed95fd88075. Report an issue: GitHub.