{"record":{"id":"5e2c34d49cdcc8d0","repo":"ruvnet/ruflo","slug":"can-only-pause-active-or-busy-agent","errorCode":null,"errorMessage":"Can only pause active or busy agent","messagePattern":"Can only pause active or busy agent","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/swarm/src/domain/entities/agent.ts","lineNumber":194,"sourceCode":"\n  /**\n   * Start the agent (transition to active)\n   */\n  start(): void {\n    if (this._status === 'terminated') {\n      throw new Error('Cannot start terminated agent');\n    }\n    this._status = 'active';\n    this._lastActiveAt = new Date();\n    this._updatedAt = new Date();\n  }\n\n  /**\n   * Pause the agent\n   */\n  pause(): void {\n    if (this._status !== 'active' && this._status !== 'busy') {\n      throw new Error('Can only pause active or busy agent');\n    }\n    this._status = 'paused';\n    this._updatedAt = new Date();\n  }\n\n  /**\n   * Resume paused agent\n   */\n  resume(): void {\n    if (this._status !== 'paused') {\n      throw new Error('Can only resume paused agent');\n    }\n    this._status = this._currentTaskIds.size > 0 ? 'busy' : 'active';\n    this._lastActiveAt = new Date();\n    this._updatedAt = new Date();\n  }\n\n  /**","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/swarm/src/domain/entities/agent.ts#L176-L212","documentation":"Agent.pause() only accepts the 'active' and 'busy' states. This error means the agent was in some other state — idle, paused (double pause), error, or terminated — when pause() was called. It is the entity guarding its state machine, not an infrastructure failure.","triggerScenarios":"Pausing an idle agent (it was created but never started) Calling pause() twice in a row (second call sees status 'paused')\nPausing an agent in 'error' state (after fail() was called) before recover()\nPausing a terminated agent Concurrent lifecycle commands from a UI and a coordinator both issuing pause","commonSituations":"UI pause buttons wired directly to agent.pause() without rendering/disabling based on current status Reconciliation loops that pause everything during deploy without filtering by state Race between an agent erroring out and an operator pausing it","solutions":["Check agent.status is 'active' or 'busy' before calling pause() (public status getter)\nMake pause idempotent in your layer: skip if already 'paused'\nFor an 'error' agent, recover() first (to idle), then start(), then pause() if still needed\nSerialize lifecycle commands per agent (queue or lock) to avoid races"],"exampleFix":"// before\nfunction onOperatorPause(agent) { agent.pause(); } // throws when idle/paused/error\n\n// after\nfunction onOperatorPause(agent) {\n  if (agent.status === 'active' || agent.status === 'busy') agent.pause();\n  // already-paused / other states: no-op\n}","handlingStrategy":"type-guard","validationCode":"const pauseable = (a) => a.status === 'active' || a.status === 'busy';\nif (pauseable(agent)) agent.pause();","typeGuard":"function isPauseable(a) { return a.status === 'active' || a.status === 'busy'; }","tryCatchPattern":"try { agent.pause(); }\ncatch (e) {\n  if (e instanceof Error && e.message === 'Can only pause active or busy agent') return; // wrong state — no-op\n  throw e;\n}","preventionTips":["Drive UI/scheduler pause actions from the agent's current status","Serialize lifecycle commands per agent to avoid double-pause races","Remember recover()->start()->pause() is the only path back from 'error' to pausable"],"tags":["agent","state-machine","lifecycle","domain-entity","typescript"],"backgroundTag":"state-machine-invalid-transition","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}