hashicorp/nomad · error

failed parsing cron expression: %s: %v

Error message

failed parsing cron expression: %s: %v

What it means

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.

Source

Thrown at api/jobs.go:965

		}
	}
	return nextTime, nil
}

// cronParseNext is a helper that parses the next time for the given expression
// but captures any panic that may occur in the underlying library.
// ---  THIS FUNCTION IS REPLICATED IN nomad/structs/structs.go
// and should be kept in sync.
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
}

func (p *PeriodicConfig) GetLocation() (*time.Location, error) {
	if p.TimeZone == nil || *p.TimeZone == "" {
		return time.UTC, nil
	}

	return time.LoadLocation(*p.TimeZone)
}

// ParameterizedJobConfig is used to configure the parameterized job.
type ParameterizedJobConfig struct {
	Payload      string   `hcl:"payload,optional"`
	MetaRequired []string `mapstructure:"meta_required" hcl:"meta_required,optional"`
	MetaOptional []string `mapstructure:"meta_optional" hcl:"meta_optional,optional"`
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Validate the spec with cronexpr.Parse (or `nomad job inspect`) before submission
  2. Use Nomad's 6-field cron syntax including seconds
  3. Correct the specific parse error included in the message
  4. Consider @daily/@hourly alternatives only if the embedded cronexpr supports them

Example fix

// before
spec = "*/15 * * *"        // missing field
// after
spec = "0 */15 * * * *"    // every 15 minutes, 6-field
Defensive patterns

Strategy: validation

Validate before calling

if _, err := cronexpr.Parse(spec); err != nil {
    return fmt.Errorf("cron spec %q invalid: %v", spec, err)
}

Try / catch

t, err := cronParseNext(time.Now(), spec)
if err != nil {
    var badSpec string
    if _, perr := fmt.Sscanf(err.Error(), "failed parsing cron expression: %q", &badSpec); perr == nil {
        return fmt.Errorf("fix spec %s", badSpec)
    }
    return err
}

Prevention

When it happens

Trigger: Registering a periodic job (jobs.Register / periodic config) with a spec cronexpr cannot parse, or calling PeriodicConfig.Next on such a config.

Common situations: 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.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/ae4ee38a8ad0e69e. Report an issue: GitHub.