{"record":{"id":"e09602e87b15e868","repo":"hashicorp/nomad","slug":"unknown-periodic-specification-type-q","errorCode":null,"errorMessage":"Unknown periodic specification type %q","messagePattern":"Unknown periodic specification type %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":5949,"sourceCode":"\tswitch p.SpecType {\n\tcase PeriodicSpecCron:\n\t\t// Validate the cron spec\n\t\tif p.Spec != \"\" {\n\t\t\tif _, err := cronexpr.Parse(p.Spec); err != nil {\n\t\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Invalid cron spec %q: %v\", p.Spec, err))\n\t\t\t}\n\t\t}\n\t\t// Validate the cron specs\n\t\tfor _, spec := range p.Specs {\n\t\t\tif _, err := cronexpr.Parse(spec); err != nil {\n\t\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Invalid cron spec %q: %v\", spec, err))\n\t\t\t}\n\t\t}\n\n\tcase PeriodicSpecTest:\n\t\t// No-op\n\tdefault:\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Unknown periodic specification type %q\", p.SpecType))\n\t}\n\n\treturn mErr.ErrorOrNil()\n}\n\nfunc (p *PeriodicConfig) Canonicalize() {\n\t// Load the location\n\tl, err := time.LoadLocation(p.TimeZone)\n\tif err != nil {\n\t\tp.location = time.UTC\n\t}\n\n\tp.location = l\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.\nfunc CronParseNext(fromTime time.Time, spec string) (t time.Time, err error) {","sourceCodeStart":5931,"sourceCodeEnd":5967,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L5931-L5967","documentation":"PeriodicConfig.Validate switches on SpecType and only recognizes the known constants (e.g. PeriodicSpecCron, PeriodicSpecTest). Any other value falls into the default case and produces this error, appended to the job's validation multierror. It protects against typos and unsupported spec types in the job file.","triggerScenarios":"Submitting a periodic job with `periodic { spec_type = \"...\" }` set to anything other than \"cron\" (or the internal test type), e.g. \"interval\", \"Cron\" (wrong case), or an empty/misspelled value.","commonSituations":"Typo in spec_type; assuming other schedule types exist (like systemd timers); copying an old/foreign config format; capitalization mismatches.","solutions":["Set spec_type = \"cron\" (the only user-facing supported value) in the periodic block.","Remove the spec_type field if the default (cron) is desired.","Check the Nomad docs/version for the set of valid PeriodicSpec constants.","Fix casing — the comparison is exact string equality."],"exampleFix":"// before\nperiodic {\n  spec = \"*/5 * * * *\"\n  spec_type = \"Interval\"\n}\n// after\nperiodic {\n  spec = \"*/5 * * * *\"\n  spec_type = \"cron\"\n}","handlingStrategy":"validation","validationCode":"func validSpecType(t string) bool {\n    switch t {\n    case \"\", \"cron\":\n        return true\n    default:\n        return false\n    }\n}\n// call before submitting: if !validSpecType(job.Periodic.SpecType) { ... }","typeGuard":null,"tryCatchPattern":"if err := job.Periodic.Validate(); err != nil {\n    // surfaces the unknown spec type; correct the field and retry\n}","preventionTips":["Only ever set spec_type = \"cron\" in user job files.","Omit spec_type to get the default.","Use constants (structs.PeriodicSpecCron) when building jobs in Go.","Never compare spec types case-insensitively — they are exact strings."],"tags":["nomad","validation","job-spec","enum"],"backgroundTag":"invalid-enum-value","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"}