hibiken/asynq · error
asynq
Error message
asynq: %w
What it means
PeriodicTaskManager.Start wraps any error from the initial configuration sync with the "asynq: " prefix. The underlying cause is almost always the config provider failing (GetConfigs error) or a config failing validation. It is a wrapper, so inspect the wrapped error for the real cause.
Solutions
- Read the wrapped error (%w chain) to find the root cause
- Verify the ConfigProvider is initialized and its backing store is reachable before Start
- Validate provider output (non-nil, valid cronspecs) before returning it from GetConfigs
Defensive patterns
Strategy: try-catch
Validate before calling
if err := mgr.p.GetConfigs(); err != nil {
return fmt.Errorf("provider not ready: %w", err)
} Try / catch
if err := mgr.Start(); err != nil {
var root error
for e := err; e != nil; e = errors.Unwrap(e) { root = e }
log.Fatalf("periodic task manager failed to start: %v (root: %v)", err, root)
} Prevention
- Unwrap the error chain with errors.Unwrap to find the true cause
- Pre-flight the provider's backing store before Start
- Log provider errors inside your GetConfigs implementation for faster diagnosis
When it happens
Trigger: Calling mgr.Start() (directly or via Run) when mgr.p.GetConfigs() returns an error, or when initialSync validation fails (nil config, nil Task, empty Cronspec, duplicate IDs).
Common situations: Redis-backed or file-based provider unreachable at startup; provider returns configs with empty cronspecs; app redeploy where the config service is not yet up.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- PeriodicTaskConfig.Cronspec cannot be empty
- initial call to GetConfigs failed
- asynq: no scheduler entry found
- asynq: the scheduler is already running
- asynq: the scheduler has already been stopped
AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07).
Data as JSON: /api/errors/17c4a70171c4ba4c.
Report an issue: GitHub.
Appendix: source
Thrown at periodic_task_manager.go:125
if c.Task == nil {
return fmt.Errorf("PeriodicTaskConfig.Task cannot be nil")
}
if c.Cronspec == "" {
return fmt.Errorf("PeriodicTaskConfig.Cronspec cannot be empty")
}
return nil
}
// Start starts a scheduler and background goroutine to sync the scheduler with the configs
// returned by the provider.
//
// Start returns any error encountered at start up time.
func (mgr *PeriodicTaskManager) Start() error {
if mgr.s == nil || mgr.p == nil {
panic("asynq: cannot start uninitialized PeriodicTaskManager; use NewPeriodicTaskManager to initialize")
}
if err := mgr.initialSync(); err != nil {
return fmt.Errorf("asynq: %w", err)
}
if err := mgr.s.Start(); err != nil {
return fmt.Errorf("asynq: %w", err)
}
mgr.wg.Add(1)
go func() {
defer mgr.wg.Done()
ticker := time.NewTicker(mgr.syncInterval)
for {
select {
case <-mgr.done:
mgr.s.logger.Debugf("Stopping syncer goroutine")
ticker.Stop()
return
case <-ticker.C:
mgr.sync()
}
}View on GitHub (pinned to d135f1439b)