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
- Check task.status === 'pending' before queue() (public getter) Make submission idempotent upstream with dedupe keys so the same task is never queued twice
- For failures/retries, rely on task.fail() (it re-queues automatically up to maxRetries) — never call queue() again yourself
- 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
- Dedupe submissions with idempotency keys before they reach the task entity
- Follow the pipeline pending -> queued -> assigned -> running -> completed exactly
- For failures, rely on fail()'s built-in re-queue instead of re-queueing by hand
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
- Cannot start terminated agent
- Can only pause active or busy agent
- Can only resume paused agent
- Can only recover from error state
- Can only assign queued or pending tasks
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/5225b58f5de2623a.
Report an issue: GitHub.