ruvnet/ruflo · error · Error
Cannot start terminated agent
Error message
Cannot start terminated agent
What it means
Agent entity (DDD aggregate) enforces its lifecycle: terminate() moves the agent to 'terminated', which is a terminal state, and start() refuses to transition out of it. Once terminated, the agent cannot be reactivated — this throw is the state machine rejecting an invalid transition.
Source
Thrown at v3/@claude-flow/swarm/src/domain/entities/agent.ts:182
get updatedAt(): Date {
return new Date(this._updatedAt);
}
get lastActiveAt(): Date {
return new Date(this._lastActiveAt);
}
// ============================================================================
// Business Logic Methods
// ============================================================================
/**
* Start the agent (transition to active)
*/
start(): void {
if (this._status === 'terminated') {
throw new Error('Cannot start terminated agent');
}
this._status = 'active';
this._lastActiveAt = new Date();
this._updatedAt = new Date();
}
/**
* Pause the agent
*/
pause(): void {
if (this._status !== 'active' && this._status !== 'busy') {
throw new Error('Can only pause active or busy agent');
}
this._status = 'paused';
this._updatedAt = new Date();
}
/**View on GitHub (pinned to fa13ee4ad6)
Solutions
- Check agent.status !== 'terminated' (the getter is public) before calling start()
- If work must continue, create a NEW agent instead of restarting a terminated one — termination is final
- Filter terminated agents out of any recovery/restart loops
- If the agent should have been idle rather than terminated, fix the earlier code path that called terminate()
Example fix
// before agents.forEach(a => a.start()); // throws for terminated agents // after agents.filter(a => a.status !== 'terminated').forEach(a => a.start());
Defensive patterns
Strategy: type-guard
Validate before calling
if (agent.status === 'terminated') {
agent = spawnReplacementAgent(agent); // termination is final — never call start()
}
agent.start(); Type guard
const canStart = (a) => a.status !== 'terminated'; // 'idle' | 'paused' | 'error' | 'active' | 'busy' -> start() legal; 'terminated' -> not if (canStart(agent)) agent.start();
Try / catch
try { agent.start(); }
catch (e) {
if (e instanceof Error && e.message === 'Cannot start terminated agent') {
agent = createAgent(config); agent.start(); return;
}
throw e;
} Prevention
- Filter terminated agents out of every restart/recovery routine
- Model 'terminated' as final in your coordinator: remove from pools on terminate()
- Prefer spawn-a-new-agent over any 'revive' logic
When it happens
Trigger: Calling agent.start() after agent.terminate() was invoked (directly or via a coordinator shutting the swarm down) Restart logic that iterates all agents calling start() without filtering out terminated ones Rehydrating an agent from persistence with status 'terminated' and running it through an activation routine
Common situations: Swarm scale-down followed by a generic 'reactivate all' routine Scheduler retry passes that don't check agent.status ORM/event-sourcing replay reaching a start() after a terminate() event
Related errors
- Can only pause active or busy agent
- Can only resume paused agent
- Can only recover from error state
- Cannot assign task to terminated agent
- Task ${taskId} not assigned to this agent
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/a072863b714f2c2d.
Report an issue: GitHub.