{"record":{"id":"cf0ef4e45993f273","repo":"hashicorp/nomad","slug":"max-delay-cannot-be-less-than-delay-v-got-v","errorCode":null,"errorMessage":"Max Delay cannot be less than Delay %v (got %v)","messagePattern":"Max Delay cannot be less than Delay (.+?) \\(got (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":6684,"sourceCode":"\tif r.Delay.Nanoseconds() < ReschedulePolicyMinDelay.Nanoseconds() {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Delay cannot be less than %v (got %v)\", ReschedulePolicyMinDelay, r.Delay))\n\t\tdelayPreCheck = false\n\t}\n\n\t// Must use a valid delay function\n\tif !isValidDelayFunction(r.DelayFunction) {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Invalid delay function %q, must be one of %q\", r.DelayFunction, RescheduleDelayFunctions))\n\t\tdelayPreCheck = false\n\t}\n\n\t// Validate MaxDelay if not using linear delay progression\n\tif r.DelayFunction != \"constant\" {\n\t\tif r.MaxDelay.Nanoseconds() < ReschedulePolicyMinDelay.Nanoseconds() {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Max Delay cannot be less than %v (got %v)\", ReschedulePolicyMinDelay, r.Delay))\n\t\t\tdelayPreCheck = false\n\t\t}\n\t\tif r.MaxDelay < r.Delay {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Max Delay cannot be less than Delay %v (got %v)\", r.Delay, r.MaxDelay))\n\t\t\tdelayPreCheck = false\n\t\t}\n\n\t}\n\n\t// Validate Interval and other delay parameters if attempts are limited\n\tif !r.Unlimited {\n\t\tif r.Interval.Nanoseconds() < ReschedulePolicyMinInterval.Nanoseconds() {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Interval cannot be less than %v (got %v)\", ReschedulePolicyMinInterval, r.Interval))\n\t\t}\n\t\tif !delayPreCheck {\n\t\t\t// We can't cross validate the rest of the delay params if delayPreCheck fails, so return early\n\t\t\treturn mErr.ErrorOrNil()\n\t\t}\n\t\tcrossValidationErr := r.validateDelayParams()\n\t\tif crossValidationErr != nil {\n\t\t\t_ = multierror.Append(&mErr, crossValidationErr)\n\t\t}","sourceCodeStart":6666,"sourceCodeEnd":6702,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L6666-L6702","documentation":"ReschedulePolicy.Validate() requires MaxDelay >= Delay for non-constant delay functions. A maximum that is smaller than the starting delay is self-contradictory (progression would start above its own ceiling), so the policy is rejected. The message prints (delay, maxDelay) in that argument order.","triggerScenarios":"A reschedule block where max_delay < delay, e.g. delay = \"2m\" with max_delay = \"1m\" and delay_function != \"constant\".","commonSituations":"Tuning delay upward after max_delay was fixed, copy-editing one value without the other, or computed policies where the cap was derived from stale inputs.","solutions":["Raise max_delay so it is >= delay.","Lower delay so it fits under the intended max_delay.","Use delay_function = \"constant\" if no progression/cap semantics are needed."],"exampleFix":"// before\nreschedule {\n  delay_function = \"linear\"\n  delay          = \"2m\"\n  max_delay      = \"1m\"\n}\n// after\nreschedule {\n  delay_function = \"linear\"\n  delay          = \"2m\"\n  max_delay      = \"1h\"\n}","handlingStrategy":"validation","validationCode":"if rsl != nil && rsl.DelayFunction != \"constant\" && rsl.MaxDelay < rsl.Delay {\n    return fmt.Errorf(\"max_delay (%v) must be >= delay (%v)\", rsl.MaxDelay, rsl.Delay)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Enforce max_delay >= delay in policy-generation code.","Update delay and max_delay together when tuning.","Use constant delay if no ceiling semantics are needed."],"tags":["nomad","validation","duration","reschedule-policy"],"backgroundTag":"invalid-config-combination","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}