hashicorp/nomad · error
Invalid time zone %q: %v
Error message
Invalid time zone %q: %v
What it means
PeriodicConfig.Validate checks that a periodic job's TimeZone field names a loadable IANA time zone via time.LoadLocation. When the zone string is non-empty but cannot be resolved (bad name or missing tz database), the validation error is appended to the job's multierror. The job spec is rejected until the time zone is corrected.
Source
Thrown at nomad/structs/structs.go:5927
}
func (p *PeriodicConfig) Validate() error {
if !p.Enabled {
return nil
}
var mErr multierror.Error
if p.Spec != "" && len(p.Specs) != 0 {
_ = multierror.Append(&mErr, fmt.Errorf("Only cron or crons may be used"))
}
if p.Spec == "" && len(p.Specs) == 0 {
_ = multierror.Append(&mErr, fmt.Errorf("Must specify a spec"))
}
// Check if we got a valid time zone
if p.TimeZone != "" {
if _, err := time.LoadLocation(p.TimeZone); err != nil {
_ = multierror.Append(&mErr, fmt.Errorf("Invalid time zone %q: %v", p.TimeZone, err))
}
}
switch p.SpecType {
case PeriodicSpecCron:
// Validate the cron spec
if p.Spec != "" {
if _, err := cronexpr.Parse(p.Spec); err != nil {
_ = multierror.Append(&mErr, fmt.Errorf("Invalid cron spec %q: %v", p.Spec, err))
}
}
// Validate the cron specs
for _, spec := range p.Specs {
if _, err := cronexpr.Parse(spec); err != nil {
_ = multierror.Append(&mErr, fmt.Errorf("Invalid cron spec %q: %v", spec, err))
}
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Set TimeZone to a valid IANA zone name, e.g. "America/New_York" or "UTC".
- Verify the name with `time.LoadLocation("Zone/Name")` in a quick Go snippet or `tzdata` lookup before submitting.
- Ensure the machine running validation has tzdata installed (/usr/share/zoneinfo); in scratch containers embed the tzdata Go package or install tzdata.
- Remove the TimeZone field entirely if the default (UTC) is acceptable.
Example fix
// before
periodic {
cron = "*/5 * * * *"
time_zone = "EST"
}
// after
periodic {
cron = "*/5 * * * *"
time_zone = "America/New_York"
} Defensive patterns
Strategy: validation
Validate before calling
func validTimeZone(tz string) bool {
if tz == "" {
return true
}
_, err := time.LoadLocation(tz)
return err == nil
}
// call before submitting: if !validTimeZone(job.Periodic.TimeZone) { ... } Prevention
- Only use IANA zone names (see `go run` of time.LoadLocation or the tzdata list).
- Prefer "UTC" when the zone doesn't matter.
- In containerized environments, install tzdata or import _ "time/tzdata".
- Lint job files with a pre-submit validation hook.
When it happens
Trigger: Submitting/validating a periodic job whose `periodic { time_zone = "..." }` is set to a string that time.LoadLocation cannot resolve, e.g. "EST5EDT" without tzdata, "UTC+2", a typo like "america/new_yorkk", or an empty-named location.
Common situations: Hand-written HCL job files with guessed zone names; using fixed offsets like "+02:00" instead of IANA names; minimal/scratch Docker images lacking /usr/share/zoneinfo so even valid names fail to load.
Related errors
- Disconnect cannot be configured with both lost_after and sto
- lost_after cannot be a negative duration
- stop_after cannot be a negative duration
- Missing job ID
- Job ID contains a space
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f9d628cf096b861e.
Report an issue: GitHub.