hashicorp/nomad · error
System or sysbatch jobs should not have a reschedule policy
Error message
System or sysbatch jobs should not have a reschedule policy
What it means
Nomad validation rejects a reschedule policy on System or SysBatch jobs. These job types run one allocation per eligible node and are not re-placed by the scheduler after failures, so a `reschedule` stanza has no effect and is considered a configuration error. Detected when `j.Type` is `JobTypeSystem` or `JobTypeSysBatch` and `tg.ReschedulePolicy != nil`.
Source
Thrown at nomad/structs/structs.go:7202
mErr = multierror.Append(mErr, fmt.Errorf("Task Group %v should have a restart policy", tg.Name))
}
if j.Type == JobTypeSystem {
if tg.Spreads != nil {
mErr = multierror.Append(mErr, fmt.Errorf("System jobs may not have a spread block"))
}
} else {
for idx, spread := range tg.Spreads {
if err := spread.Validate(); err != nil {
outer := fmt.Errorf("Spread %d validation failed: %s", idx+1, err)
mErr = multierror.Append(mErr, outer)
}
}
}
if j.Type == JobTypeSystem || j.Type == JobTypeSysBatch {
if tg.ReschedulePolicy != nil {
mErr = multierror.Append(mErr, fmt.Errorf("System or sysbatch jobs should not have a reschedule policy"))
}
} else {
if tg.ReschedulePolicy != nil {
if err := tg.ReschedulePolicy.Validate(); err != nil {
mErr = multierror.Append(mErr, err)
}
} else {
mErr = multierror.Append(mErr, fmt.Errorf("Task Group %v should have a reschedule policy", tg.Name))
}
}
if tg.EphemeralDisk != nil {
if err := tg.EphemeralDisk.Validate(); err != nil {
mErr = multierror.Append(mErr, err)
}
} else {
mErr = multierror.Append(mErr, fmt.Errorf("Task Group %v should have an ephemeral disk object", tg.Name))
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove the `reschedule` block from each task group in the system/sysbatch job.
- If rescheduling on failure is required, use a `service` (or `batch`) job type instead.
- Validate the job spec with `nomad job validate` before submission.
Example fix
// before
job "backup" {
type = "sysbatch"
group "backup" {
reschedule {
attempts = 3
interval = "10m"
}
}
}
// after
job "backup" {
type = "sysbatch"
group "backup" {
}
} Defensive patterns
Strategy: validation
Validate before calling
func validateNoRescheduleOnSystem(j *api.Job) error {
if j == nil {
return nil
}
if *j.Type == "system" || *j.Type == "sysbatch" {
for _, tg := range j.TaskGroups {
if tg.ReschedulePolicy != nil && *tg.ReschedulePolicy != (api.ReschedulePolicy{}) {
return fmt.Errorf("group %s: system/sysbatch jobs should not have a reschedule policy", *tg.Name)
}
}
}
return nil
} Type guard
func isSystemFamily(j *api.Job) bool { return j != nil && (*j.Type == "system" || *j.Type == "sysbatch") } Prevention
- Strip lifecycle stanzas (reschedule, spread) when changing a job's type.
- Use separate HCL templates per job type instead of one shared template.
- Add a pre-submit validation step in CI pipelines.
When it happens
Trigger: Submitting a job with `type = "system"` or `type = "sysbatch"` whose task group defines a `reschedule { ... }` stanza, or where reschedule policy is set programmatically on the group.
Common situations: Converting a service job to system/sysbatch without stripping the reschedule block; shared base group templates that include reschedule for all job types; older job files carried forward across job-type changes.
Related errors
- Task Group %v should have a reschedule policy
- ErrConnectRequireOneNetwork
- ErrConnectInvalidNetworkMode
- service.port must be set for mesh gateway service
- non-default Consul cluster requires Nomad Enterprise
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/fff5b87a7771ee3f.
Report an issue: GitHub.