{"record":{"id":"6c5c83b9f30222f7","repo":"hashicorp/nomad","slug":"invalid-healthcheck-q","errorCode":null,"errorMessage":"Invalid HealthCheck: %q","messagePattern":"Invalid HealthCheck: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":6851,"sourceCode":"\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()\n}\n\n// TaskGroup is an atomic unit of placement. Each task group belongs to","sourceCodeStart":6833,"sourceCodeEnd":6869,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L6833-L6869","documentation":"MigrateStrategy.Validate accepts only \"checks\" (MigrateStrategyHealthChecks) or \"states\" (MigrateStrategyHealthStates) for HealthCheck; any other non-empty value hits the default case and is rejected with this formatted error quoting the invalid value. This ensures migration health evaluation has a known implementation.","triggerScenarios":"Submitting a job whose update block has health_checks set to a string other than \"checks\" or \"states\" (e.g. \"health\", \"consul\", or case-variant \"Checks\").","commonSituations":"Typos or wrong casing in HCL; copying terminology from Consul/other tools ('health_checks', 'grpc'); schema drift from generated configs.","solutions":["Change health_checks to exactly \"checks\" or \"states\" (lowercase).","Check spelling and case; values are matched literally against the constants.","Consult the Nomad update-block docs for allowed values.","Run `nomad job validate` to confirm."],"exampleFix":"// before\nupdate {\n  max_parallel  = 1\n  health_checks = \"health\"\n}\n// after\nupdate {\n  max_parallel  = 1\n  health_checks = \"checks\"\n}","handlingStrategy":"validation","validationCode":"var validHealthChecks = map[string]bool{\"checks\": true, \"states\": true}\nfunc validHealthCheckValue(m *structs.MigrateStrategy) error {\n\tif m.HealthCheck != \"\" && !validHealthChecks[m.HealthCheck] {\n\t\treturn fmt.Errorf(\"health_checks must be checks|states, got %q\", m.HealthCheck)\n\t}\n\treturn nil\n}","typeGuard":"func isKnownHealthCheck(v string) bool {\n\treturn v == structs.MigrateStrategyHealthChecks || v == structs.MigrateStrategyHealthStates || v == \"\"\n}","tryCatchPattern":"if err := strategy.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"Invalid HealthCheck\") {\n\t\t// map/normalize the value to \"checks\" or \"states\" before resubmit\n\t}\n}","preventionTips":["Only use the exact lowercase literals \"checks\" and \"states\".","Normalize case before assigning HealthCheck in generated configs.","Compare against the exported constants instead of string literals in Go code.","Lint job templates for unknown update-block keys/values."],"tags":["nomad","go","validation","migrate-strategy","enum"],"backgroundTag":"invalid-enum-value","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"}