{"record":{"id":"24ade752330a713b","repo":"ruvnet/ruflo","slug":"can-only-complete-running-tasks","errorCode":null,"errorMessage":"Can only complete running tasks","messagePattern":"Can only complete running tasks","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/swarm/src/domain/entities/task.ts","lineNumber":206,"sourceCode":"  }\n\n  /**\n   * Start task execution\n   */\n  start(): void {\n    if (this._status !== 'assigned') {\n      throw new Error('Can only start assigned tasks');\n    }\n    this._status = 'running';\n    this._startedAt = new Date();\n  }\n\n  /**\n   * Complete the task successfully\n   */\n  complete(output?: unknown): void {\n    if (this._status !== 'running') {\n      throw new Error('Can only complete running tasks');\n    }\n    this._status = 'completed';\n    this._output = output;\n    this._completedAt = new Date();\n  }\n\n  /**\n   * Mark task as failed\n   */\n  fail(error: string): void {\n    if (this._status !== 'running' && this._status !== 'assigned') {\n      throw new Error('Can only fail running or assigned tasks');\n    }\n    this._error = error;\n    this._retryCount++;\n\n    if (this._retryCount >= this._maxRetries) {\n      this._status = 'failed';","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/swarm/src/domain/entities/task.ts#L188-L224","documentation":"Task.complete(output?) finalizes a task from the 'running' state only. This throw occurs when complete() is called on a task that is pending, queued, assigned, or already finished (completed/failed/cancelled) — including double completion and completion of cancelled work.","triggerScenarios":"Calling complete() twice (second sees 'completed')\nCompleting a task that was cancelled mid-run (status 'cancelled')\nCompleting an 'assigned' task that never had start() called (fast-path shortcuts skipping start)\nRace: fail() already marked the task 'failed' (retries exhausted) when success arrived late\nCompletion delivered to the wrong task instance after retry-based reassignment","commonSituations":"At-least-once completion events without idempotency\nLate success callbacks racing timeouts that already failed the task\nWorkers cancelled (SIGTERM) while their completion message is in flight Optimistic-concurrency violations when two replicas complete the same task","solutions":["Make completion idempotent: skip when task.status !== 'running'\nGuard against races by funnelling complete/fail through one state owner per task (version check or lock)\nIf a cancel arrived first, drop the late completion (or surface it as a 'zombie result' metric)\nNever skip start() — the pipeline pending/queued -> assigned -> start -> complete must be followed in order"],"exampleFix":"// before\nawait run(task);\ntask.complete(result); // throws if cancelled/failed/double-completed meanwhile\n\n// after\nawait run(task);\nif (task.status === 'running') task.complete(result);\nelse reportZombieResult(task.id, result); // cancelled/failed/dup — log, don't throw","handlingStrategy":"type-guard","validationCode":"if (task.status === 'running') task.complete(result);\nelse reportZombieResult(task.id, result); // cancelled/failed/double-complete","typeGuard":"function isCompletable(t) { return t.status === 'running'; }","tryCatchPattern":"try { task.complete(output); }\ncatch (e) {\n  if (e instanceof Error && e.message === 'Can only complete running tasks') return; // idempotent skip\n  throw e;\n}","preventionTips":["Make completion idempotent at the call site (check status or dedupe by taskId)\nSingle-flight complete/fail per task to break timeout-vs-success races","Follow the full lifecycle; never complete an 'assigned' task that skipped start()"],"tags":["task","state-machine","idempotency","task-lifecycle","typescript"],"backgroundTag":"state-machine-invalid-transition","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}