ruvnet/ruflo · error · Error

Agent has ${currentTasks} active tasks. Use force=true to te

Error message

Agent has ${currentTasks} active tasks. Use force=true to terminate anyway.

What it means

TerminateAgentCommandHandler refuses to terminate an agent whose currentTaskCount > 0 unless input.force === true, protecting in-flight tasks from being orphaned. The message itself documents the escape hatch: re-issue the command with force=true when losing active work is acceptable.

Source

Thrown at v3/@claude-flow/swarm/src/application/commands/spawn-agent.command.ts:110

  tasksReassigned: number;
}

/**
 * Terminate Agent Command Handler
 */
export class TerminateAgentCommandHandler {
  constructor(private readonly repository: IAgentRepository) {}

  async execute(input: TerminateAgentInput): Promise<TerminateAgentResult> {
    const agent = await this.repository.findById(input.agentId);
    if (!agent) {
      throw new Error(`Agent '${input.agentId}' not found`);
    }

    const currentTasks = agent.currentTaskCount;

    if (currentTasks > 0 && !input.force) {
      throw new Error(`Agent has ${currentTasks} active tasks. Use force=true to terminate anyway.`);
    }

    agent.terminate();
    await this.repository.save(agent);

    return {
      success: true,
      agentId: input.agentId,
      tasksReassigned: currentTasks,
    };
  }
}

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Let the agent's tasks complete (or reassign them) and terminate again without force.
  2. If losing in-flight work is acceptable, re-send the command with force: true.
  3. Cancel the agent's outstanding tasks first, then terminate.
  4. In shutdown paths, drain or reassign task queues before terminating agents.

Example fix

// before
await terminateAgent.execute({ agentId }); // agent has N active tasks

// after — option A: accept losing in-flight tasks
await terminateAgent.execute({ agentId, force: true });

// after — option B: drain first, then terminate normally
await drainOrReassignTasks(agentId);
await terminateAgent.execute({ agentId });
Defensive patterns

Strategy: validation

Validate before calling

const agent = await agentRepository.findById(agentId);
if (!agent) throw new Error(`unknown agent ${agentId}`);
const force = agent.currentTaskCount > 0 && inFlightWorkIsExpendable;
if (agent.currentTaskCount > 0 && !force) {
  await drainOrReassignTasks(agentId); // wait for tasks first
}
await terminateAgentHandler.execute({ agentId, force });

Try / catch

try {
  await terminateAgentHandler.execute({ agentId });
} catch (e) {
  if (e instanceof Error && e.message.includes('active tasks. Use force=true')) {
    // either drain/reassign tasks and retry without force,
    // or retry once with force: true if losing the work is acceptable
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Terminating a busy agent without force while it still holds tasks; tasks that are stuck and never complete, blocking cleanup; a shutdown script that does not drain agent work queues first; scale-down logic selecting agents at random regardless of load.

Common situations: Autoscaler scale-down picking busy agents; operators killing agents during an incident with queued work; tests terminating agents without force while mock tasks are assigned.

Related errors


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