hibiken/asynq · error
PeriodicTaskConfig cannot be nil
Error message
PeriodicTaskConfig cannot be nil
What it means
validatePeriodicTaskConfig returns this error when a config entry supplied by the PeriodicTaskConfigProvider is nil. The sync loop (initialSync/sync) validates every provider-returned config before enqueuing, and a nil pointer cannot describe a task. It surfaces during the manager's periodic sync rather than at construction.
Solutions
- Filter nil entries out of the slice in the provider before returning it
- Return an explicit error from the provider when data is incomplete
- Log and skip invalid rows at the data source instead of emitting nil configs
Example fix
// before
func getConfigs() ([]*asynq.PeriodicTaskConfig, error) {
return []*asynq.PeriodicTaskConfig{cfgFromDB(row1), cfgFromDB(row2)}, nil // may contain nil
}
// after
func getConfigs() ([]*asynq.PeriodicTaskConfig, error) {
var out []*asynq.PeriodicTaskConfig
for _, row := range rows {
if c := cfgFromDB(row); c != nil { out = append(out, c) }
}
return out, nil
} Defensive patterns
Strategy: validation
Validate before calling
cfgs, err := provider()
if err != nil { return err }
for i, c := range cfgs {
if c == nil { return fmt.Errorf("config at index %d is nil", i) }
} Type guard
func validConfig(c *asynq.PeriodicTaskConfig) bool { return c != nil } Try / catch
if err := mgr.Run(); err != nil {
if strings.Contains(err.Error(), "PeriodicTaskConfig cannot be nil") {
// inspect provider output for nil entries
}
return err
} Prevention
- Filter nil entries from provider output
- Fail the provider with a clear error instead of returning nil elements
- Unit-test the provider against real data sources
- Log skipped rows at the source
When it happens
Trigger: A PeriodicTaskConfigProvider callback returns a slice containing a nil *PeriodicTaskConfig element, causing sync to fail with this error at every sync interval.
Common situations: Building the config list from a database/flag source where some rows are empty; appending to a slice with a conditional that appends nil; JSON/YAML unmarshalling producing nil entries.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- PeriodicTaskConfig.Task cannot be nil
- PeriodicTaskConfigProvider cannot be nil
- task ID cannot be empty
- Unique TTL cannot be less than 1s
- group key cannot be empty
AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07).
Data as JSON: /api/errors/7d48befc5f549cd0.
Report an issue: GitHub.
Appendix: source
Thrown at periodic_task_manager.go:105
Opts []Option // optional: can be nil
}
func (c *PeriodicTaskConfig) hash() string {
h := sha256.New()
_, _ = h.Write([]byte(c.Cronspec))
_, _ = h.Write([]byte(c.Task.Type()))
h.Write(c.Task.Payload())
opts := stringifyOptions(c.Opts)
sort.Strings(opts)
for _, opt := range opts {
_, _ = h.Write([]byte(opt))
}
return fmt.Sprintf("%x", h.Sum(nil))
}
func validatePeriodicTaskConfig(c *PeriodicTaskConfig) error {
if c == nil {
return fmt.Errorf("PeriodicTaskConfig cannot be nil")
}
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")
}View on GitHub (pinned to d135f1439b)