hibiken/asynq · warning

queue is not paused

Error message

queue %q is not paused

What it means

Returned by RDB.Unpause when the queue has no paused-key, i.e. it is not currently paused. Unpause deletes the paused-key; if Del removes 0 keys the queue was never paused and this error is returned. Purely a state-validation error.

Solutions

  1. Check IsPaused(queue) before calling Unpause
  2. Ignore this error when the goal is simply 'queue is running'
  3. Centralize pause-state management to avoid races
  4. Re-issue Pause if the paused key was unintentionally lost

Example fix

// before
if err := inspector.Unpause(q); err != nil {
    return err
}
// after
paused, err := inspector.IsPaused(q)
if err != nil { return err }
if paused {
    if err := inspector.Unpause(q); err != nil { return err }
}
Defensive patterns

Strategy: validation

Validate before calling

paused, err := inspector.IsPaused(q)
if err != nil { return err }
if !paused { return nil } // already running

Try / catch

if err := inspector.Unpause(q); err != nil && !strings.Contains(err.Error(), "not paused") {
    return err
} // treat not-paused as success

Prevention

When it happens

Trigger: Calling inspector.Unpause(queue) on a queue that is active (never paused or already unpaused), possibly concurrently unpaused by another process.

Common situations: Ops scripts that unpause all queues blindly; double-click/two workers handling the same unpause request; after a Redis restart where the paused key was lost.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07). Data as JSON: /api/errors/d8ee3330269ad434. Report an issue: GitHub.

Appendix: source

Thrown at internal/rdb/inspect.go:2095

	ok, err := r.client.SetNX(context.Background(), key, r.clock.Now().Unix(), 0).Result()
	if err != nil {
		return err
	}
	if !ok {
		return fmt.Errorf("queue %q is already paused", qname)
	}
	return nil
}

// Unpause resumes processing of tasks from the given queue.
func (r *RDB) Unpause(qname string) error {
	key := base.PausedKey(qname)
	deleted, err := r.client.Del(context.Background(), key).Result()
	if err != nil {
		return err
	}
	if deleted == 0 {
		return fmt.Errorf("queue %q is not paused", qname)
	}
	return nil
}

// ClusterKeySlot returns an integer identifying the hash slot the given queue hashes to.
func (r *RDB) ClusterKeySlot(qname string) (int64, error) {
	key := base.PendingKey(qname)
	return r.client.ClusterKeySlot(context.Background(), key).Result()
}

// ClusterNodes returns a list of nodes the given queue belongs to.
func (r *RDB) ClusterNodes(qname string) ([]redis.ClusterNode, error) {
	keyslot, err := r.ClusterKeySlot(qname)
	if err != nil {
		return nil, err
	}
	clusterSlots, err := r.client.ClusterSlots(context.Background()).Result()
	if err != nil {

View on GitHub (pinned to d135f1439b)