{"record":{"id":"993ae9b0d266dced","repo":"hashicorp/nomad","slug":"missing-healthcheck","errorCode":null,"errorMessage":"Missing HealthCheck","messagePattern":"Missing HealthCheck","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":6848,"sourceCode":"\t\tHealthCheck:     MigrateStrategyHealthChecks,\n\t\tMinHealthyTime:  10 * time.Second,\n\t\tHealthyDeadline: 5 * time.Minute,\n\t}\n}\n\nfunc (m *MigrateStrategy) Validate() error {\n\tvar mErr multierror.Error\n\n\tif m.MaxParallel < 0 {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"MaxParallel must be >= 0 but found %d\", m.MaxParallel))\n\t}\n\n\tswitch m.HealthCheck {\n\tcase MigrateStrategyHealthChecks, MigrateStrategyHealthStates:\n\t\t// ok\n\tcase \"\":\n\t\tif m.MaxParallel > 0 {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Missing HealthCheck\"))\n\t\t}\n\tdefault:\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"Invalid HealthCheck: %q\", m.HealthCheck))\n\t}\n\n\tif m.MinHealthyTime < 0 {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"MinHealthyTime is %s and must be >= 0\", m.MinHealthyTime))\n\t}\n\n\tif m.HealthyDeadline < 0 {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"HealthyDeadline is %s and must be >= 0\", m.HealthyDeadline))\n\t}\n\n\tif m.MinHealthyTime > m.HealthyDeadline {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"MinHealthyTime must be less than HealthyDeadline\"))\n\t}\n\n\treturn mErr.ErrorOrNil()","sourceCodeStart":6830,"sourceCodeEnd":6866,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L6830-L6866","documentation":"MigrateStrategy.Validate requires a HealthCheck value when MaxParallel > 0, because migrations need a health criterion (checks or states) to decide which allocations are healthy. An empty HealthCheck with active migration concurrency yields this error. It prevents deploying migrations that can never evaluate allocation health.","triggerScenarios":"Submitting a job with update block: max_parallel set (>0) but health_checks omitted/empty string.","commonSituations":"Minimal update blocks that only specify max_parallel; HCL files migrated from older job specs; generated configs that omit health_checks assuming a default.","solutions":["Add health_checks = \"checks\" (uses Nomad service checks) to the update block.","Or use health_checks = \"states\" to rely on allocation/task states only.","Set max_parallel = 0 if no migration behavior is desired, making HealthCheck optional.","Validate the job spec before submission."],"exampleFix":"// before\nupdate {\n  max_parallel = 1\n}\n// after\nupdate {\n  max_parallel  = 1\n  health_checks = \"checks\"\n}","handlingStrategy":"validation","validationCode":"func validHealthCheck(m *structs.MigrateStrategy) error {\n\tif m.MaxParallel > 0 && m.HealthCheck == \"\" {\n\t\treturn errors.New(\"health_checks is required when max_parallel > 0\")\n\t}\n\treturn nil\n}","typeGuard":"func hasHealthCheckWhenMigrating(m *structs.MigrateStrategy) bool {\n\treturn m.MaxParallel <= 0 || m.HealthCheck != \"\"\n}","tryCatchPattern":"if err := strategy.Validate(); err != nil {\n\tif err.Error() == \"Missing HealthCheck\" {\n\t\t// set health_checks to \"checks\" or \"states\" before resubmit\n\t}\n}","preventionTips":["Always pair max_parallel > 0 with an explicit health_checks value.","Use \"checks\" when Consul/Nomad service checks exist, else \"states\".","Include health_checks in job-spec templates by default.","Run `nomad job validate` as a pre-submit gate."],"tags":["nomad","go","validation","migrate-strategy","deployment"],"backgroundTag":"missing-required-argument","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}