hashicorp/nomad · error
Nomad can't restart the TaskGroup %v times in an interval of
Error message
Nomad can't restart the TaskGroup %v times in an interval of %v with a delay of %v
What it means
RestartPolicy.Validate() requires that attempts * delay fit within interval. If the product of the restart attempts and the delay between them exceeds the interval, Nomad could not physically perform the configured restarts in the window, so the policy is rejected as mathematically impossible.
Source
Thrown at nomad/structs/structs.go:6583
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 {
switch jobType {
case JobTypeService, JobTypeSystem:
rp := DefaultServiceJobRestartPolicy
return &rp
case JobTypeBatch:
rp := DefaultBatchJobRestartPolicy
return &rp
}
return nil
}
const ReschedulePolicyMinInterval = 15 * time.Second
const ReschedulePolicyMinDelay = 1 * time.SecondView on GitHub (pinned to 482b49bf1a)
Solutions
- Increase interval so it is >= attempts * delay.
- Reduce attempts or delay until the product fits the interval.
- Validate the arithmetic: e.g. attempts=5, delay=15s needs interval >= 75s.
Example fix
// before
restart {
interval = "30m"
attempts = 5
delay = "10m"
}
// after
restart {
interval = "1h"
attempts = 5
delay = "10m"
} Defensive patterns
Strategy: validation
Validate before calling
if rp != nil && time.Duration(rp.Attempts)*rp.Delay > rp.Interval {
return fmt.Errorf("attempts*delay (%v) exceeds interval (%v)", time.Duration(rp.Attempts)*rp.Delay, rp.Interval)
} Prevention
- Recompute interval whenever attempts or delay changes.
- Assert attempts*delay <= interval in policy-generation tests.
- Prefer defaults from NewRestartPolicy which satisfy the constraint.
When it happens
Trigger: A restart block where time.Duration(attempts) * delay > interval, e.g. attempts = 5, delay = "10m", interval = "30m" (50m > 30m).
Common situations: Tuning attempts upward after lowering interval, or setting a long delay for backoff without recomputing the interval; very common after scaling attempts for flaky services.
Related errors
- Interval can not be less than %v (got %v)
- KillTimeout must be a positive value
- gcs_timeout not a valid duration: %w
- gcs_timeout must be > 0
- git_timeout not a valid duration: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/80b6fae3018da2a7.
Report an issue: GitHub.