hashicorp/nomad · error

Delay cannot be less than %v (got %v)

Error message

Delay cannot be less than %v (got %v)

What it means

ReschedulePolicy.Validate() enforces a minimum delay (ReschedulePolicyMinDelay, 30s by default) between reschedule attempts. A delay below that floor is rejected because Nomad will not reschedule a failed allocation more aggressively than this.

Source

Thrown at nomad/structs/structs.go:6667

		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
	}

	// Validate MaxDelay if not using linear delay progression
	if r.DelayFunction != "constant" {
		if r.MaxDelay.Nanoseconds() < ReschedulePolicyMinDelay.Nanoseconds() {
			_ = multierror.Append(&mErr, fmt.Errorf("Max Delay cannot be less than %v (got %v)", ReschedulePolicyMinDelay, r.Delay))
			delayPreCheck = false
		}
		if r.MaxDelay < r.Delay {
			_ = multierror.Append(&mErr, fmt.Errorf("Max Delay cannot be less than Delay %v (got %v)", r.Delay, r.MaxDelay))
			delayPreCheck = false

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Raise reschedule.delay to at least 30s (default is 30s).
  2. If faster recovery is the goal, tune delay_function/max_delay instead of lowering the floor.
  3. Validate durations explicitly, e.g. delay = "30s".

Example fix

// before
reschedule {
  attempts = 5
  interval = "1h"
  delay    = "5s"
}
// after
reschedule {
  attempts = 5
  interval = "1h"
  delay    = "30s"
}
Defensive patterns

Strategy: validation

Validate before calling

if rsl != nil && rsl.Delay.Nanoseconds() < structs.ReschedulePolicyMinDelay.Nanoseconds() {
    return fmt.Errorf("reschedule delay %v < minimum %v", rsl.Delay, structs.ReschedulePolicyMinDelay)
}

Prevention

When it happens

Trigger: A reschedule block with delay set below the minimum (e.g. delay = "5s"), or a delay parsed with the wrong unit (plain integer seconds vs duration string).

Common situations: Trying to make failover faster by shrinking delay, copying delay values from restart policy examples (which allow smaller values), or unit mistakes in generated jobs.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/7d2ad47868331974. Report an issue: GitHub.