hashicorp/nomad · error
failed parsing cron expression: %s: %v
Error message
failed parsing cron expression: %s: %v
What it means
In CronParseNext, if cronexpr.Parse itself fails to parse the spec, the parse error is wrapped into this message containing the spec and the underlying error. Unlike the panic-recovery path, this fires before any Next() evaluation, directly from cronexpr.Parse.
Source
Thrown at nomad/structs/structs.go:5976
if err != nil {
p.location = time.UTC
}
p.location = l
}
// CronParseNext is a helper that parses the next time for the given expression
// but captures any panic that may occur in the underlying library.
func CronParseNext(fromTime time.Time, spec string) (t time.Time, err error) {
defer func() {
if recover() != nil {
t = time.Time{}
err = fmt.Errorf("failed parsing cron expression: %q", spec)
}
}()
exp, err := cronexpr.Parse(spec)
if err != nil {
return time.Time{}, fmt.Errorf("failed parsing cron expression: %s: %v", spec, err)
}
return exp.Next(fromTime), nil
}
// 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.TimeView on GitHub (pinned to 482b49bf1a)
Solutions
- Correct the spec string reported in the error to a valid 5-field cron expression.
- Run cronexpr.Parse on the spec before calling CronParseNext to fail fast.
- Ensure the job goes through job validation (which catches bad specs) before being registered.
- Trim whitespace/hidden characters from programmatically built spec strings.
Example fix
// before t, err := structs.CronParseNext(now, "* * *") // after t, err := structs.CronParseNext(now, "* * * * *")
Defensive patterns
Strategy: validation
Validate before calling
func safeCronParseNext(from time.Time, spec string) (time.Time, error) {
if _, err := cronexpr.Parse(spec); err != nil {
return time.Time{}, err // fail before CronParseNext
}
return structs.CronParseNext(from, spec)
} Try / catch
t, err := structs.CronParseNext(fromTime, spec)
if err != nil {
return time.Time{}, fmt.Errorf("skipping eval: %w", err)
} Prevention
- Parse specs once at config load time; reuse validated expressions.
- Route all job registration through the validation endpoint.
- Sanitize spec strings (trim, strip control chars) from API input.
When it happens
Trigger: Calling structs.CronParseNext (directly or via PeriodicConfig.Next) with a spec string that cronexpr.Parse rejects — wrong field count, invalid tokens, malformed steps.
Common situations: Runtime dispatch of a periodic job whose spec bypassed validation (e.g. stored pre-validation or constructed programmatically); config loaded from an API with hand-built specs.
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/609521aa9fb0c859.
Report an issue: GitHub.