{"record":{"id":"7e08e4e82317c03d","repo":"hashicorp/nomad","slug":"reschedule-policy-has-unlimited-attempts-enabled-a","errorCode":null,"errorMessage":"Reschedule policy has unlimited attempts enabled and a low delay; reschedule thrashing possible","messagePattern":"Reschedule policy has unlimited attempts enabled and a low delay; reschedule thrashing possible","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"nomad/structs/structs.go","lineNumber":7673,"sourceCode":"\n\tif tg.StopAfterClientDisconnect != nil {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"StopAfterClientDisconnect is deprecated and ignored favor of Disconnect.StopOnClientAfter\"))\n\t}\n\n\tif tg.PreventRescheduleOnLost {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"PreventRescheduleOnLost is deprecated and ignored in favor of Disconnect.Replace\"))\n\t}\n\n\t// Warn about unbounded rescheduling which may cause thrashing if tasks have\n\t// unlimited attempts and a low delay.\n\t//\n\t// The 5 second gate on the delay is used as this was the previous minimum\n\t// value which did not produce a warning. It therefore feels like the right\n\t// gate to use.\n\tif rp := tg.ReschedulePolicy; rp != nil && rp.Unlimited && rp.Delay < 5*time.Second {\n\t\tmErr.Errors = append(\n\t\t\tmErr.Errors,\n\t\t\terrors.New(\"Reschedule policy has unlimited attempts enabled and a low delay; reschedule thrashing possible\"),\n\t\t)\n\t}\n\n\t// Check for mbits network field\n\tif len(tg.Networks) > 0 && tg.Networks[0].MBits > 0 {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"mbits has been deprecated as of Nomad 0.12.0. Please remove mbits from the network block\"))\n\t}\n\n\t// Validate group-level services.\n\tfor _, s := range tg.Services {\n\t\tif err := s.Warnings(); err != nil {\n\t\t\terr = multierror.Prefix(err, fmt.Sprintf(\"Service %q:\", s.Name))\n\t\t\tmErr = *multierror.Append(&mErr, err)\n\t\t}\n\t}\n\n\tfor _, t := range tg.Tasks {\n\t\tif err := t.Warnings(); err != nil {","sourceCodeStart":7655,"sourceCodeEnd":7691,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L7655-L7691","documentation":"TaskGroup.Validate warns when the group's reschedule policy enables Unlimited attempts while Delay is under 5 seconds. Unlimited fast retries can cause reschedule thrashing, repeatedly restarting the allocation in a tight loop. It is a warning-level validation error appended to the group multierror.","triggerScenarios":"A group has `reschedule { unlimited = true, delay = \"1s\" }` (Delay < 5s and DelayFunction leading to low delays) — either set explicitly or inherited from a namespace/agent default when the job overrides the policy.","commonSituations":"Hand-written reschedule blocks with very small delays; copied examples tuned for batch jobs but applied to services that will never become healthy.","solutions":["Set reschedule delay >= 5s, e.g. delay = \"30s\".","Or disable unlimited: `reschedule { unlimited = false, attempts = 5 }`.","Or remove the reschedule block entirely to use sensible defaults."],"exampleFix":"// before\nreschedule {\n  unlimited = true\n  delay     = \"1s\"\n}\n// after\nreschedule {\n  unlimited = false\n  attempts  = 5\n  delay     = \"30s\"\n  max_delay = \"1h\"\n}","handlingStrategy":"validation","validationCode":"if rp := tg.ReschedulePolicy; rp != nil && rp.Unlimited && rp.Delay < 5*time.Second {\n  log.Warn(\"unlimited reschedule with low delay may thrash\")\n}","typeGuard":"func isThrashRisk(rp *structs.ReschedulePolicy) bool {\n  return rp != nil && rp.Unlimited && rp.Delay < 5*time.Second\n}","tryCatchPattern":null,"preventionTips":["Keep reschedule delay >= 5s when unlimited is enabled.","Use attempts + interval instead of unlimited for non-critical services.","Check namespace/agent reschedule defaults too.","Monitor restart counts in the Nomad UI for thrash symptoms."],"tags":["nomad","reschedule-policy","configuration","validation"],"backgroundTag":"reschedule-thrashing","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"}