hashicorp/nomad · error
Job type %q does not allow max_run_duration
Error message
Job type %q does not allow max_run_duration
What it means
During Job validation in nomad/structs/structs.go, if a task group sets max_run_duration, only batch and sysbatch job types are permitted to use it. Any other job type (service, system, etc.) with max_run_duration set causes this error to be appended to the multierror returned by Job.Validate. It exists because max_run_duration semantics (killing/rescheduling the allocation after a fixed duration) only make sense for batch-style workloads.
Source
Thrown at nomad/structs/structs.go:7156
// could be a lone consul gateway inserted by the connect mutator
mErr = multierror.Append(mErr, errors.New("Missing tasks for task group"))
}
if tg.Disconnect != nil {
if err := tg.Disconnect.Validate(j); err != nil {
mErr = multierror.Append(mErr, err)
}
}
if tg.MaxRunDuration != nil {
if *tg.MaxRunDuration <= 0 {
mErr = multierror.Append(mErr, errors.New("MaxRunDuration must be greater than zero"))
}
switch j.Type {
case JobTypeBatch, JobTypeSysBatch:
default:
mErr = multierror.Append(mErr, fmt.Errorf("Job type %q does not allow max_run_duration", j.Type))
}
}
for idx, constr := range tg.Constraints {
if err := constr.Validate(); err != nil {
outer := fmt.Errorf("Constraint %d validation failed: %s", idx+1, err)
mErr = multierror.Append(mErr, outer)
}
}
if j.Type == JobTypeSystem {
if tg.Affinities != nil {
mErr = multierror.Append(mErr, fmt.Errorf("System jobs may not have an affinity block"))
}
} else {
for idx, affinity := range tg.Affinities {
if err := affinity.Validate(); err != nil {
outer := fmt.Errorf("Affinity %d validation failed: %s", idx+1, err)
mErr = multierror.Append(mErr, outer)View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove the max_run_duration field from the task group if the job is not batch/sysbatch.
- Change the job type to "batch" or "sysbatch" if the workload really is finite/periodic.
- If you need periodic behavior for a service job, use a separate batch job with cron/periodic config instead.
Example fix
// before
job "svc" {
type = "service"
group "web" {
max_run_duration = "1h"
}
}
// after
job "svc" {
type = "service"
group "web" {
# max_run_duration removed: not allowed for service jobs
}
} Defensive patterns
Strategy: validation
Validate before calling
func validateMaxRunDuration(jobType string, groups []map[string]interface{}) error {
for _, tg := range groups {
if _, ok := tg["max_run_duration"]; ok && jobType != "batch" && jobType != "sysbatch" {
return fmt.Errorf("group %v: max_run_duration not allowed for job type %q", tg["name"], jobType)
}
}
return nil
} Type guard
func allowsMaxRunDuration(jobType string) bool {
return jobType == "batch" || jobType == "sysbatch"
} Prevention
- Only emit max_run_duration from templates when job type is batch/sysbatch.
- Run `nomad job validate` in CI before every submit.
- Keep service job HCL free of batch-only fields.
When it happens
Trigger: Submitting (job register/plan) a job spec where any task group defines max_run_duration (directly or via `max_run_duration` in the group block) while the job `type` is not "batch" or "sysbatch" — e.g. type = "service" or "system".
Common situations: Copy-pasting a batch job HCL/JSON that includes max_run_duration into a service job; converting a scheduled batch task into a long-running service without removing the duration cap; tooling that templates max_run_duration into every group.
Related errors
- ErrConnectRequireOneNetwork
- ErrConnectInvalidNetworkMode
- service.port must be set for mesh gateway service
- non-default Consul cluster requires Nomad Enterprise
- numa scheduling requires Nomad Enterprise
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/322fff13196164ea.
Report an issue: GitHub.