ruvnet/ruflo · error · Error

Can only queue pending tasks

Error message

Can only queue pending tasks

What it means

Task.queue() transitions a task from 'pending' to 'queued' and only accepts 'pending'. This throw means the task was already queued, assigned, running, or finished — i.e., it entered the pipeline twice.

Source

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

    return new Date(this._createdAt);
  }
  get startedAt(): Date | undefined {
    return this._startedAt ? new Date(this._startedAt) : undefined;
  }
  get completedAt(): Date | undefined {
    return this._completedAt ? new Date(this._completedAt) : undefined;
  }

  // ============================================================================
  // Business Logic
  // ============================================================================

  /**
   * Queue the task for execution
   */
  queue(): void {
    if (this._status !== 'pending') {
      throw new Error('Can only queue pending tasks');
    }
    this._status = 'queued';
  }

  /**
   * Assign task to an agent
   */
  assign(agentId: string): void {
    if (this._status !== 'queued' && this._status !== 'pending') {
      throw new Error('Can only assign queued or pending tasks');
    }
    this._assignedAgentId = agentId;
    this._status = 'assigned';
  }

  /**
   * Start task execution
   */

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Check task.status === 'pending' before queue() (public getter) Make submission idempotent upstream with dedupe keys so the same task is never queued twice
  2. For failures/retries, rely on task.fail() (it re-queues automatically up to maxRetries) — never call queue() again yourself
  3. For event replay, skip transitions that don't match the expected pre-state

Example fix

// before
submit(task); submit(task); // second queue() throws

// after
function submit(task) { if (task.status === 'pending') task.queue(); }
Defensive patterns

Strategy: type-guard

Validate before calling

if (task.status === 'pending') task.queue();
// retries: let task.fail() handle re-queueing — never call queue() again manually

Type guard

function isQueueable(t) { return t.status === 'pending'; }

Try / catch

try { task.queue(); }
catch (e) {
  if (e instanceof Error && e.message === 'Can only queue pending tasks') return; // already admitted
  throw e;
}

Prevention

When it happens

Trigger: Double-submission of the same Task entity (two code paths calling queue() on one instance) Re-queueing manually instead of using the retry path inside fail() (fail() already resets to 'queued') Persistence replay re-applying a queue event to a task rehydrated as 'queued' Producer/consumer both calling queue() on a shared reference

Common situations: Duplicate job submissions from retries at the API layer without idempotency keys Event-sourced rebuilds where 'queued' events replay onto already-queued tasks Scheduler restarts re-admitting in-flight tasks

Related errors


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