hashicorp/nomad · error

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

Error message

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

What it means

ReschedulePolicy.Validate() requires MaxDelay to be at least ReschedulePolicyMinDelay for any delay_function other than "constant" (progressive functions grow the delay up to MaxDelay, so a valid ceiling is mandatory). Note the message prints r.Delay in the 'got' slot even though it checks r.MaxDelay — a known quirk of this error string.

Source

Thrown at nomad/structs/structs.go:6680

	}

	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
		}

	}

	// Validate Interval and other delay parameters if attempts are limited
	if !r.Unlimited {
		if r.Interval.Nanoseconds() < ReschedulePolicyMinInterval.Nanoseconds() {
			_ = multierror.Append(&mErr, fmt.Errorf("Interval cannot be less than %v (got %v)", ReschedulePolicyMinInterval, r.Interval))
		}
		if !delayPreCheck {
			// We can't cross validate the rest of the delay params if delayPreCheck fails, so return early
			return mErr.ErrorOrNil()
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set max_delay to a duration >= 30s (e.g. max_delay = "1h").
  2. If a fixed delay is wanted, use delay_function = "constant" so max_delay is not required.
  3. Ignore the misleading '(got ...)' value — fix max_delay itself.

Example fix

// before
reschedule {
  delay_function = "exponential"
  delay          = "30s"
}
// after
reschedule {
  delay_function = "exponential"
  delay          = "30s"
  max_delay      = "1h"
}
Defensive patterns

Strategy: validation

Validate before calling

if rsl != nil && rsl.DelayFunction != "constant" && rsl.MaxDelay.Nanoseconds() < structs.ReschedulePolicyMinDelay.Nanoseconds() {
    return fmt.Errorf("non-constant delay_function requires max_delay >= %v", structs.ReschedulePolicyMinDelay)
}

Prevention

When it happens

Trigger: A reschedule block with delay_function = "linear"/"exponential"/"fibonacci" and max_delay below the minimum (e.g. 0 or < 30s), typically when max_delay was omitted or zero-valued in code-built policies.

Common situations: Omitting max_delay while setting a non-constant delay function, passing max_delay as an untyped zero, or unit mistakes making the duration tiny.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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