hashicorp/nomad · error
Reschedule Policy with Attempts = %v, Interval = %v, and Unl
Error message
Reschedule Policy with Attempts = %v, Interval = %v, and Unlimited = %v is ambiguous
What it means
ReschedulePolicy.Validate() rejects a policy that both limits reschedules (Attempts > 0) and sets Unlimited = true. Unlimited means 'keep rescheduling forever', which contradicts a finite attempt count, so the combination is ambiguous and disallowed.
Source
Thrown at nomad/structs/structs.go:6658
return enabled
}
// Validate uses different criteria to validate the reschedule policy
// Delay must be a minimum of 1 second
// Delay Ceiling is ignored if Delay Function is "constant"
// Number of possible attempts is validated, given the interval, delay and delay function
func (r *ReschedulePolicy) Validate() error {
if !r.Enabled() {
return nil
}
var mErr multierror.Error
// Check for ambiguous/confusing settings
if r.Attempts > 0 {
if r.Interval <= 0 {
_ = multierror.Append(&mErr, fmt.Errorf("Interval must be a non zero value if Attempts > 0"))
}
if r.Unlimited {
_ = multierror.Append(&mErr, fmt.Errorf("Reschedule Policy with Attempts = %v, Interval = %v, "+
"and Unlimited = %v is ambiguous", r.Attempts, r.Interval, r.Unlimited))
_ = multierror.Append(&mErr, errors.New("If Attempts >0, Unlimited cannot also be set to true"))
}
}
delayPreCheck := true
// Delay should be bigger than the default
if r.Delay.Nanoseconds() < ReschedulePolicyMinDelay.Nanoseconds() {
_ = multierror.Append(&mErr, fmt.Errorf("Delay cannot be less than %v (got %v)", ReschedulePolicyMinDelay, r.Delay))
delayPreCheck = false
}
// Must use a valid delay function
if !isValidDelayFunction(r.DelayFunction) {
_ = multierror.Append(&mErr, fmt.Errorf("Invalid delay function %q, must be one of %q", r.DelayFunction, RescheduleDelayFunctions))
delayPreCheck = false
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove unlimited = true if you want a limited policy.
- Set attempts = 0 (and drop interval) if you truly want unlimited rescheduling.
- Choose one style: {attempts>0, interval>0, unlimited=false} or {attempts=0, unlimited=true}.
Example fix
// before
reschedule {
attempts = 5
interval = "1h"
unlimited = true
}
// after
reschedule {
attempts = 5
interval = "1h"
unlimited = false
} Defensive patterns
Strategy: validation
Validate before calling
if rsl != nil && rsl.Attempts > 0 && rsl.Unlimited {
return fmt.Errorf("reschedule policy cannot set both attempts>0 and unlimited=true")
} Type guard
func rescheduleModeConsistent(r *structs.ReschedulePolicy) bool {
return !(r.Attempts > 0 && r.Unlimited)
} Prevention
- Pick one mode: limited (attempts/interval) or unlimited; never mix.
- When overriding defaults programmatically, reset conflicting fields.
- Document unlimited=true semantics in job templates.
When it happens
Trigger: A reschedule block with attempts > 0 and unlimited = true together, or programmatic policy construction where attempts defaults above 0 while unlimited is set true.
Common situations: Users adding unlimited = true to 'be safe' without zeroing attempts; templates that always emit unlimited; merging default policies (attempts>0) with user overrides (unlimited=true).
Related errors
- Reschedule policy has unlimited attempts enabled and a low d
- Interval must be a non zero value if Attempts > 0
- Delay cannot be less than %v (got %v)
- Invalid delay function %q, must be one of %q
- Max Delay cannot be less than %v (got %v)
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/88b74e7c03b3b58b.
Report an issue: GitHub.