hibiken/asynq · error

asynq: no scheduler entry found

Error message

asynq: no scheduler entry found

What it means

Scheduler.Unregister returns this error when no entry with the given entryID exists in the scheduler's idmap. Unregister only removes known entries; deleting an unknown ID is treated as a caller mistake and reported instead of being silently ignored.

Solutions

  1. Only call Unregister for IDs previously returned/accepted by Register
  2. Ignore or special-case this error if best-effort removal is intended (idempotent delete)
  3. Track registered IDs in your own set and check membership before Unregister

Example fix

// before
if err := s.Unregister(id); err != nil { return err }
// after
if err := s.Unregister(id); err != nil && !strings.Contains(err.Error(), "no scheduler entry found") {
    return err
}
Defensive patterns

Strategy: type-guard

Validate before calling

if !registered[id] {
    return nil // nothing to unregister
}

Type guard

func canUnregister(s *asynq.Scheduler, id string) bool {
    return s != nil && registeredEntries[id]
}

Try / catch

if err := s.Unregister(id); err != nil {
    if strings.Contains(err.Error(), "no scheduler entry found") {
        return nil // already gone; treat as idempotent success
    }
    return err
}

Prevention

When it happens

Trigger: Calling s.Unregister(id) for an ID that was never Register-ed, was already unregistered, or whose registration failed; ID mismatch due to formatting (whitespace, case).

Common situations: Unregistering tasks from a config store when the entry was deleted elsewhere first; duplicate cleanup paths unregistering the same ID twice; restart wiping in-memory entries while callers still hold old IDs.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at scheduler.go:239

	}
	cronID, err := s.cron.AddJob(cronspec, job)
	if err != nil {
		return "", err
	}
	s.mu.Lock()
	s.idmap[job.id.String()] = cronID
	s.mu.Unlock()
	return job.id.String(), nil
}

// Unregister removes a registered entry by entry ID.
// Unregister returns a non-nil error if no entries were found for the given entryID.
func (s *Scheduler) Unregister(entryID string) error {
	s.mu.Lock()
	defer s.mu.Unlock()
	cronID, ok := s.idmap[entryID]
	if !ok {
		return fmt.Errorf("asynq: no scheduler entry found")
	}
	delete(s.idmap, entryID)
	s.cron.Remove(cronID)
	return nil
}

// Run starts the scheduler until an os signal to exit the program is received.
// It returns an error if scheduler is already running or has been shutdown.
func (s *Scheduler) Run() error {
	if err := s.Start(); err != nil {
		return err
	}
	s.waitForSignals()
	s.Shutdown()
	return nil
}

// Start starts the scheduler.

View on GitHub (pinned to d135f1439b)