ruvnet/ruflo · warning

Cannot cancel finished tasks

Error message

Cannot cancel finished tasks

What it means

Task.cancel() refuses to cancel tasks whose status is 'completed' or 'failed' — terminal states cannot be undone by cancellation. Any other state (pending, queued, assigned, running, even cancelled again) is cancellable. This is the entity protecting result finality.

Solutions

  1. Check task.status is not 'completed'/'failed' before cancel() (or make cancel idempotent: 'cancelled' re-cancel is already allowed by this guard, finished is not) Break the completion/cancel race with per-task single-flight transitions Discard stale cancel commands using task version numbers or completion timestamps In UIs, disable cancel once the task reaches a terminal state

Example fix

// before
cancelBtn.onclick = () => task.cancel(); // throws for finished tasks

// after
cancelBtn.onclick = () => {
  if (task.status !== 'completed' && task.status !== 'failed') task.cancel();
};
Defensive patterns

Strategy: type-guard

Validate before calling

const cancellable = (t) => t.status !== 'completed' && t.status !== 'failed';
if (cancellable(task)) task.cancel();

Type guard

function isCancellable(t) { return t.status !== 'completed' && t.status !== 'failed'; }
// note: cancelling an already-'cancelled' task is legal (guard only blocks terminal states)

Try / catch

try { task.cancel(); }
catch (e) {
  if (e instanceof Error && e.message === 'Cannot cancel finished tasks') return; // already final
  throw e;
}

Prevention

When it happens

Trigger: Cancel requests arriving after the task already completed (user hits cancel on a finished job) Timeout supervisor cancelling every in-flight task, including ones that finished a tick earlier Double-cancel of a 'failed' task by both a retry-abort path and a shutdown sweep UI showing stale status so operators cancel finished tasks

Common situations: At-least-once cancellation events without status checks Shutdown routines sweeping the task store and cancelling everything regardless of state Race between a worker's completion and a deadline-triggered cancel

Related errors


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

Appendix: source

Thrown at v3/@claude-flow/swarm/src/domain/entities/task.ts:238

    this._error = error;
    this._retryCount++;

    if (this._retryCount >= this._maxRetries) {
      this._status = 'failed';
      this._completedAt = new Date();
    } else {
      // Reset for retry
      this._status = 'queued';
      this._assignedAgentId = undefined;
    }
  }

  /**
   * Cancel the task
   */
  cancel(): void {
    if (this._status === 'completed' || this._status === 'failed') {
      throw new Error('Cannot cancel finished tasks');
    }
    this._status = 'cancelled';
    this._completedAt = new Date();
  }

  /**
   * Check if all dependencies are satisfied
   */
  areDependenciesSatisfied(completedTaskIds: Set<string>): boolean {
    for (const depId of this._dependencies) {
      if (!completedTaskIds.has(depId)) {
        return false;
      }
    }
    return true;
  }

  /**

View on GitHub (pinned to fa13ee4ad6)