ruvnet/ruflo · error
Agent not found: ${agentId}
Error message
Agent not found: ${agentId} What it means
LifecycleManager.terminate() resolves the agent through pool.get(agentId) and throws when the lookup returns undefined. The pool is an in-memory Map with no persistence, so the ID was either never spawned by this manager instance or was already removed by an earlier terminate(). This guard is the standard failure mode for lifecycle operations on unknown agents.
Source
Thrown at v3/@claude-flow/shared/src/core/orchestrator/lifecycle-manager.ts:168
return { id: config.id, agent: null, error };
}
});
const settled = await Promise.allSettled(spawnPromises);
for (const result of settled) {
if (result.status === 'fulfilled' && result.value.agent) {
results.set(result.value.id, result.value.agent);
}
}
return results;
}
async terminate(agentId: string, reason?: string): Promise<void> {
const agent = this.pool.get(agentId);
if (!agent) {
throw new Error(`Agent not found: ${agentId}`);
}
agent.status = 'terminated';
// Remove from pool
this.pool.remove(agentId);
this.eventBus.emit(SystemEventTypes.AGENT_TERMINATED, {
agentId,
reason: reason ?? 'User requested',
});
}
async terminateAll(reason?: string): Promise<void> {
const agents = this.pool.getAll();
await Promise.allSettled(
agents.map(agent => this.terminate(agent.id, reason)),
);View on GitHub (pinned to fa13ee4ad6)
Solutions
- Check lifecycle.getAgent(agentId) before calling terminate() and treat undefined as already-removed
- Make shutdown idempotent: wrap terminate() in try-catch and ignore 'Agent not found' during teardown
- If the agent should exist, verify you are calling the same LifecycleManager instance that spawned it
Example fix
// before
await lifecycle.terminate(agentId);
// after
if (lifecycle.getAgent(agentId)) {
await lifecycle.terminate(agentId);
} Defensive patterns
Strategy: validation
Validate before calling
if (!lifecycle.getAgent(agentId)) {
// already removed or never spawned; nothing to terminate
return;
}
await lifecycle.terminate(agentId, reason); Type guard
function isLiveAgent(lifecycle: LifecycleManager, id: string): boolean {
return lifecycle.getAgent(id) !== undefined;
} Try / catch
try {
await lifecycle.terminate(agentId);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Agent not found')) return; // idempotent teardown
throw e;
} Prevention
- Check getAgent(id) before every terminate() call
- Make shutdown paths idempotent and tolerate 'Agent not found'
- Remember the pool is in-memory: never reuse IDs across process restarts
When it happens
Trigger: Calling terminate(agentId) twice (the first call already did pool.remove); passing an ID produced by a different LifecycleManager instance or a previous process run; racing terminateAll() against terminate() for the same agent; a typo'd or stale ID.
Common situations: Double-termination in cleanup paths (e.g. both a test afterEach hook and explicit shutdown); storing agent IDs externally and reusing them after a service restart; concurrent shutdown handlers racing each other.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Agent '${input.agentId}' not found
- SSRF guard: invalid URL — ${rawUrl}
- Agent ${this.id} is not available (status: ${this.status})
- Agent ${this.id} not initialized. Call initialize() first.
- Agent has ${currentTasks} active tasks. Use force=true to te
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/b2fbb978428dbb88.
Report an issue: GitHub.