hashicorp/nomad · error
Invalid HealthCheck: %q
Error message
Invalid HealthCheck: %q
What it means
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.
Source
Thrown at nomad/structs/structs.go:6851
}
}
func (m *MigrateStrategy) Validate() error {
var mErr multierror.Error
if m.MaxParallel < 0 {
_ = multierror.Append(&mErr, fmt.Errorf("MaxParallel must be >= 0 but found %d", m.MaxParallel))
}
switch m.HealthCheck {
case MigrateStrategyHealthChecks, MigrateStrategyHealthStates:
// ok
case "":
if m.MaxParallel > 0 {
_ = multierror.Append(&mErr, fmt.Errorf("Missing HealthCheck"))
}
default:
_ = multierror.Append(&mErr, fmt.Errorf("Invalid HealthCheck: %q", m.HealthCheck))
}
if m.MinHealthyTime < 0 {
_ = multierror.Append(&mErr, fmt.Errorf("MinHealthyTime is %s and must be >= 0", m.MinHealthyTime))
}
if m.HealthyDeadline < 0 {
_ = multierror.Append(&mErr, fmt.Errorf("HealthyDeadline is %s and must be >= 0", m.HealthyDeadline))
}
if m.MinHealthyTime > m.HealthyDeadline {
_ = multierror.Append(&mErr, fmt.Errorf("MinHealthyTime must be less than HealthyDeadline"))
}
return mErr.ErrorOrNil()
}
// TaskGroup is an atomic unit of placement. Each task group belongs toView on GitHub (pinned to 482b49bf1a)
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.
Example fix
// before
update {
max_parallel = 1
health_checks = "health"
}
// after
update {
max_parallel = 1
health_checks = "checks"
} Defensive patterns
Strategy: validation
Validate before calling
var validHealthChecks = map[string]bool{"checks": true, "states": true}
func validHealthCheckValue(m *structs.MigrateStrategy) error {
if m.HealthCheck != "" && !validHealthChecks[m.HealthCheck] {
return fmt.Errorf("health_checks must be checks|states, got %q", m.HealthCheck)
}
return nil
} Type guard
func isKnownHealthCheck(v string) bool {
return v == structs.MigrateStrategyHealthChecks || v == structs.MigrateStrategyHealthStates || v == ""
} Try / catch
if err := strategy.Validate(); err != nil {
if strings.Contains(err.Error(), "Invalid HealthCheck") {
// map/normalize the value to "checks" or "states" before resubmit
}
} Prevention
- 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.
When it happens
Trigger: 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").
Common situations: Typos or wrong casing in HCL; copying terminology from Consul/other tools ('health_checks', 'grpc'); schema drift from generated configs.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- MaxParallel must be >= 0 but found %d
- Missing HealthCheck
- MinHealthyTime is %s and must be >= 0
- HealthyDeadline is %s and must be >= 0
- MinHealthyTime must be less than HealthyDeadline
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/6c5c83b9f30222f7.
Report an issue: GitHub.