Tencent/WeKnora · error

task %s in queue %s cannot run now

Error message

task %s in queue %s cannot run now

What it means

RunRuntimeTask wraps asynq's inspector RunTask with a permission check. Before running a task it fetches the RuntimeTask via GetRuntimeTask and verifies its state allows RuntimeTaskActionRunNow. If the task does not exist (nil) or its current state (e.g. active, archived, completed) does not permit 'run now', this error is returned instead of forwarding to asynq.

Source

Thrown at internal/router/task_inspector.go:659

	info, err := projectRuntimeTask(task, workers[task.Queue+"\x00"+task.ID])
	if err != nil {
		return nil, true, err
	}
	return &info, true, nil
}

// RunRuntimeTask moves a scheduled, retry, or archived task to pending. Asynq
// deliberately preserves the retry counter.
func (a *asynqTaskInspector) RunRuntimeTask(ctx context.Context, queue, taskID string) (bool, error) {
	if a == nil || a.inspector == nil {
		return false, nil
	}
	task, _, err := a.GetRuntimeTask(ctx, queue, taskID)
	if err != nil {
		return true, err
	}
	if task == nil || !task.Allows(types.RuntimeTaskActionRunNow) {
		return true, fmt.Errorf("task %s in queue %s cannot run now", taskID, queue)
	}
	return true, a.inspector.RunTask(queue, taskID)
}

func (a *asynqTaskInspector) DeleteRuntimeTask(ctx context.Context, queue, taskID string) (bool, error) {
	if a == nil || a.inspector == nil {
		return false, nil
	}
	task, _, err := a.GetRuntimeTask(ctx, queue, taskID)
	if err != nil {
		return true, err
	}
	if task == nil || !task.Allows(types.RuntimeTaskActionDelete) {
		return true, fmt.Errorf("task %s in queue %s cannot be deleted", taskID, queue)
	}
	return true, a.inspector.DeleteTask(queue, taskID)
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Re-fetch the queue's task list and confirm the task still exists and is in a state that permits RunNow (e.g. pending/scheduled/retry) before calling again
  2. Verify the taskID and queue name are correct and paired (task IDs are per-queue)
  3. If the task is active, wait for it to finish or cancel it instead of forcing a run
  4. If the intent is to remove a stuck task, use the force-delete path rather than run-now

Example fix

// before
tasks, _ := inspector.ListRuntimeTasks(ctx, "emails")
inspector.RunRuntimeTask(ctx, "emails", tasks[0].ID) // may already be active
// after
task, _, _ := inspector.GetRuntimeTask(ctx, "emails", taskID)
if task != nil && task.Allows(types.RuntimeTaskActionRunNow) {
    inspector.RunRuntimeTask(ctx, "emails", taskID)
}
Defensive patterns

Strategy: validation

Validate before calling

task, _, err := inspector.GetRuntimeTask(ctx, queue, taskID)
if err != nil { return err }
if task == nil || !task.Allows(types.RuntimeTaskActionRunNow) {
    return fmt.Errorf("skip: task %s in queue %s not runnable now", taskID, queue)
}

Type guard

func canRunNow(t types.RuntimeTask) bool { return t != nil && t.Allows(types.RuntimeTaskActionRunNow) }

Try / catch

var stateErr *interface{ Error() string }
if err := inspector.RunRuntimeTask(ctx, queue, taskID); err != nil {
    if strings.Contains(err.Error(), "cannot run now") { /* treat as no-op / refresh UI */ }
    return err
}

Prevention

When it happens

Trigger: Calling RunRuntimeTask(ctx, queue, taskID) for a taskID that does not exist in the queue, or whose task state denies the RunNow action — e.g. the task is currently active/being processed, is in a completed/archived state, or belongs to a queue other than the one passed.

Common situations: A UI 'Run now' button fires after the task already started or was consumed; the task ID was copied from a different queue; the task was picked up by a worker between listing and clicking run; retrying an already-succeeded task.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/336e22b934fead92. Report an issue: GitHub.