{"record":{"id":"ae4ee38a8ad0e69e","repo":"hashicorp/nomad","slug":"failed-parsing-cron-expression-s-v-ae4ee3","errorCode":null,"errorMessage":"failed parsing cron expression: %s: %v","messagePattern":"failed parsing cron expression: (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/jobs.go","lineNumber":965,"sourceCode":"\t\t}\n\t}\n\treturn nextTime, nil\n}\n\n// cronParseNext is a helper that parses the next time for the given expression\n// but captures any panic that may occur in the underlying library.\n// ---  THIS FUNCTION IS REPLICATED IN nomad/structs/structs.go\n// and should be kept in sync.\nfunc cronParseNext(fromTime time.Time, spec string) (t time.Time, err error) {\n\tdefer func() {\n\t\tif recover() != nil {\n\t\t\tt = time.Time{}\n\t\t\terr = fmt.Errorf(\"failed parsing cron expression: %q\", spec)\n\t\t}\n\t}()\n\texp, err := cronexpr.Parse(spec)\n\tif err != nil {\n\t\treturn time.Time{}, fmt.Errorf(\"failed parsing cron expression: %s: %v\", spec, err)\n\t}\n\treturn exp.Next(fromTime), nil\n}\n\nfunc (p *PeriodicConfig) GetLocation() (*time.Location, error) {\n\tif p.TimeZone == nil || *p.TimeZone == \"\" {\n\t\treturn time.UTC, nil\n\t}\n\n\treturn time.LoadLocation(*p.TimeZone)\n}\n\n// ParameterizedJobConfig is used to configure the parameterized job.\ntype ParameterizedJobConfig struct {\n\tPayload      string   `hcl:\"payload,optional\"`\n\tMetaRequired []string `mapstructure:\"meta_required\" hcl:\"meta_required,optional\"`\n\tMetaOptional []string `mapstructure:\"meta_optional\" hcl:\"meta_optional,optional\"`\n}","sourceCodeStart":947,"sourceCodeEnd":983,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/api/jobs.go#L947-L983","documentation":"cronParseNext's normal error path: when cronexpr.Parse rejects the spec, it returns 'failed parsing cron expression: %s: %v' with the spec and the cronexpr error. Unlike [527], this is a returned error, not a recovered panic.","triggerScenarios":"Registering a periodic job (jobs.Register / periodic config) with a spec cronexpr cannot parse, or calling PeriodicConfig.Next on such a config.","commonSituations":"5-field vs 6-field format confusion; '@hourly' style descriptors unsupported in some cronexpr versions; stray characters or missing fields in HCL/JSON job files.","solutions":["Validate the spec with cronexpr.Parse (or `nomad job inspect`) before submission","Use Nomad's 6-field cron syntax including seconds","Correct the specific parse error included in the message","Consider @daily/@hourly alternatives only if the embedded cronexpr supports them"],"exampleFix":"// before\nspec = \"*/15 * * *\"        // missing field\n// after\nspec = \"0 */15 * * * *\"    // every 15 minutes, 6-field","handlingStrategy":"validation","validationCode":"if _, err := cronexpr.Parse(spec); err != nil {\n    return fmt.Errorf(\"cron spec %q invalid: %v\", spec, err)\n}","typeGuard":null,"tryCatchPattern":"t, err := cronParseNext(time.Now(), spec)\nif err != nil {\n    var badSpec string\n    if _, perr := fmt.Sscanf(err.Error(), \"failed parsing cron expression: %q\", &badSpec); perr == nil {\n        return fmt.Errorf(\"fix spec %s\", badSpec)\n    }\n    return err\n}","preventionTips":["Validate cron specs in CI before job submission","Avoid hand-editing HCL cron fields without linting","Document Nomad's 6-field cron requirement for operators"],"tags":["cron","validation","periodic-jobs"],"backgroundTag":"invalid-cron-expression","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}