hashicorp/nomad · error
Unsupported restart mode: %q
Error message
Unsupported restart mode: %q
What it means
RestartPolicy.Validate() in nomad/structs/structs.go rejects a restart policy whose Mode is neither "delay" nor "fail". Nomad only supports these two restart modes; anything else (typo, wrong case, empty string) fails job validation before the job is registered. It is appended to a multierror and surfaced with the rest of the job validation errors.
Source
Thrown at nomad/structs/structs.go:6570
// RenderTemplates is flag to explicitly render all templates on task restart
RenderTemplates bool
}
func (r *RestartPolicy) Copy() *RestartPolicy {
if r == nil {
return nil
}
nrp := new(RestartPolicy)
*nrp = *r
return nrp
}
func (r *RestartPolicy) Validate() error {
var mErr multierror.Error
switch r.Mode {
case RestartPolicyModeDelay, RestartPolicyModeFail:
default:
_ = multierror.Append(&mErr, fmt.Errorf("Unsupported restart mode: %q", r.Mode))
}
// Check for ambiguous/confusing settings
if r.Attempts == 0 && r.Mode != RestartPolicyModeFail {
_ = multierror.Append(&mErr, fmt.Errorf("Restart policy %q with %d attempts is ambiguous", r.Mode, r.Attempts))
}
if r.Interval.Nanoseconds() < RestartPolicyMinInterval.Nanoseconds() {
_ = multierror.Append(&mErr, fmt.Errorf("Interval can not be less than %v (got %v)", RestartPolicyMinInterval, r.Interval))
}
if time.Duration(r.Attempts)*r.Delay > r.Interval {
_ = multierror.Append(&mErr,
fmt.Errorf("Nomad can't restart the TaskGroup %v times in an interval of %v with a delay of %v", r.Attempts, r.Interval, r.Delay))
}
return mErr.ErrorOrNil()
}
func NewRestartPolicy(jobType string) *RestartPolicy {View on GitHub (pinned to 482b49bf1a)
Solutions
- Set restart_policy.mode to exactly "delay" (default) or "fail" in the task group.
- Run `nomad job validate <file>` or POST to /v1/validate before submitting to catch the typo.
- Check casing: values are lowercase and quoted in HCL/JSON.
Example fix
// before
restart {
interval = "30m"
attempts = 2
mode = "always"
}
// after
restart {
interval = "30m"
attempts = 2
mode = "delay"
} Defensive patterns
Strategy: validation
Validate before calling
validModes := map[string]bool{"delay": true, "fail": true}
if rp := tg.RestartPolicy; rp != nil && !validModes[rp.Mode] {
return fmt.Errorf("restart_policy.mode %q must be \"delay\" or \"fail\"", rp.Mode)
} Type guard
func validRestartMode(m string) bool { return m == "delay" || m == "fail" } Prevention
- Only ever write mode = "delay" or mode = "fail" in job files.
- Run `nomad job validate` in CI before every job submit.
- Reuse the structs.RestartPolicyMode* constants when building policies in Go.
When it happens
Trigger: Submitting a job (POST /v1/jobs) or validating one (POST /v1/validate) whose task group's restart_policy.mode is set to any string other than "delay" or "fail", e.g. "always", "never", "Delay", or an empty value.
Common situations: Copy-pasting restart config from another orchestrator (e.g. Docker's or Kubernetes' restart vocabulary), typos like "restrat" or "delay-mode", YAML/HCL key confusion that leaves mode empty, or upgrading from an older/custom build that accepted other modes.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Restart policy %q with %d attempts is ambiguous
- 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
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/100215315e545505.
Report an issue: GitHub.