hashicorp/nomad · error
failed parsing cron expression %s: %v
Error message
failed parsing cron expression %s: %v
What it means
PeriodicConfig.Next iterates the multiple Specs entries, calling CronParseNext for each to find the earliest next-fire time. If any individual spec fails (parse error or panic from CronParseNext), the whole computation aborts with this error naming the failing spec and the wrapped cause.
Source
Thrown at nomad/structs/structs.go:5998
// Next returns the closest time instant matching the spec that is after the
// passed time. If no matching instance exists, the zero value of time.Time is
// returned. The `time.Location` of the returned value matches that of the
// passed time.
func (p *PeriodicConfig) Next(fromTime time.Time) (time.Time, error) {
switch p.SpecType {
case PeriodicSpecCron:
// Single spec parsing
if p.Spec != "" {
return CronParseNext(fromTime, p.Spec)
}
// multiple specs parsing
var nextTime time.Time
for _, spec := range p.Specs {
t, err := CronParseNext(fromTime, spec)
if err != nil {
return time.Time{}, fmt.Errorf("failed parsing cron expression %s: %v", spec, err)
}
if nextTime.IsZero() || t.Before(nextTime) {
nextTime = t
}
}
return nextTime, nil
case PeriodicSpecTest:
split := strings.Split(p.Spec, ",")
if len(split) == 1 && split[0] == "" {
return time.Time{}, nil
}
// Parse the times
times := make([]time.Time, len(split))
for i, s := range split {
unix, err := strconv.Atoi(s)
if err != nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Fix the spec named in the error message to a valid cron expression and update the job.
- Re-run `nomad job validate` on the job file to catch all bad specs before registration.
- Remove the offending spec from the Specs list if it is unnecessary.
- Add a CI/pre-registration check parsing every spec with cronexpr.
Example fix
// before
periodic {
specs = ["*/5 * * * *", "60 * * * *"] // 60 is invalid minute
}
// after
periodic {
specs = ["*/5 * * * *", "0 * * * *"]
} Defensive patterns
Strategy: validation
Validate before calling
func earliestNext(from time.Time, specs []string) (time.Time, error) {
for _, s := range specs {
if _, err := cronexpr.Parse(s); err != nil {
return time.Time{}, fmt.Errorf("spec %q: %w", s, err)
}
}
return job.Periodic.Next(from)
} Try / catch
next, err := periodic.Next(now)
if err != nil {
log.Printf("periodic eval failed: %v", err)
// skip this tick or fix the spec
} Prevention
- Validate the entire Specs list at registration time.
- Fix the exact spec quoted in the error before re-registering.
- Avoid editing specs directly via the raw API; use validated job files.
- Monitor scheduler logs for repeated eval failures.
When it happens
Trigger: Evaluating the next launch time of a periodic job configured with a Specs list where at least one entry is unparseable or panics cronexpr during evaluation.
Common situations: A job registered with an invalid entry in specs (perhaps edited server-side or via API without full validation); scheduler tick encountering a legacy job from an older format.
Related errors
- failed parsing cron expression: %s: %v
- must specify cron block
- timeout cannot be negative
- error parsing reserved_ports: %w
- error parsing reserved_ports for network %q: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/fedc2d387d1d75bb.
Report an issue: GitHub.