{"record":{"id":"7d48befc5f549cd0","repo":"hibiken/asynq","slug":"periodictaskconfig-cannot-be-nil","errorCode":null,"errorMessage":"PeriodicTaskConfig cannot be nil","messagePattern":"PeriodicTaskConfig cannot be nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"periodic_task_manager.go","lineNumber":105,"sourceCode":"\tOpts     []Option // optional: can be nil\n}\n\nfunc (c *PeriodicTaskConfig) hash() string {\n\th := sha256.New()\n\t_, _ = h.Write([]byte(c.Cronspec))\n\t_, _ = h.Write([]byte(c.Task.Type()))\n\th.Write(c.Task.Payload())\n\topts := stringifyOptions(c.Opts)\n\tsort.Strings(opts)\n\tfor _, opt := range opts {\n\t\t_, _ = h.Write([]byte(opt))\n\t}\n\treturn fmt.Sprintf(\"%x\", h.Sum(nil))\n}\n\nfunc validatePeriodicTaskConfig(c *PeriodicTaskConfig) error {\n\tif c == nil {\n\t\treturn fmt.Errorf(\"PeriodicTaskConfig cannot be nil\")\n\t}\n\tif c.Task == nil {\n\t\treturn fmt.Errorf(\"PeriodicTaskConfig.Task cannot be nil\")\n\t}\n\tif c.Cronspec == \"\" {\n\t\treturn fmt.Errorf(\"PeriodicTaskConfig.Cronspec cannot be empty\")\n\t}\n\treturn nil\n}\n\n// Start starts a scheduler and background goroutine to sync the scheduler with the configs\n// returned by the provider.\n//\n// Start returns any error encountered at start up time.\nfunc (mgr *PeriodicTaskManager) Start() error {\n\tif mgr.s == nil || mgr.p == nil {\n\t\tpanic(\"asynq: cannot start uninitialized PeriodicTaskManager; use NewPeriodicTaskManager to initialize\")\n\t}","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/hibiken/asynq/blob/d135f1439bee74e989b7f9b41ecd542cc87f024a/periodic_task_manager.go#L87-L123","documentation":"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.","triggerScenarios":"A PeriodicTaskConfigProvider callback returns a slice containing a nil *PeriodicTaskConfig element, causing sync to fail with this error at every sync interval.","commonSituations":"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.","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"],"exampleFix":"// before\nfunc getConfigs() ([]*asynq.PeriodicTaskConfig, error) {\n    return []*asynq.PeriodicTaskConfig{cfgFromDB(row1), cfgFromDB(row2)}, nil // may contain nil\n}\n// after\nfunc getConfigs() ([]*asynq.PeriodicTaskConfig, error) {\n    var out []*asynq.PeriodicTaskConfig\n    for _, row := range rows {\n        if c := cfgFromDB(row); c != nil { out = append(out, c) }\n    }\n    return out, nil\n}","handlingStrategy":"validation","validationCode":"cfgs, err := provider()\nif err != nil { return err }\nfor i, c := range cfgs {\n    if c == nil { return fmt.Errorf(\"config at index %d is nil\", i) }\n}","typeGuard":"func validConfig(c *asynq.PeriodicTaskConfig) bool { return c != nil }","tryCatchPattern":"if err := mgr.Run(); err != nil {\n    if strings.Contains(err.Error(), \"PeriodicTaskConfig cannot be nil\") {\n        // inspect provider output for nil entries\n    }\n    return err\n}","preventionTips":["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"],"tags":["validation","nil-check","periodic-tasks"],"backgroundTag":"schema-validation-failed","analyzedSha":"d135f1439bee74e989b7f9b41ecd542cc87f024a","analyzedAt":"2026-09-07T19:02:34.660Z","contentChangedAt":"2026-09-07T19:02:34.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}