hashicorp/nomad · error
Service %s kind must be one of consul service kind or empty
Error message
Service %s kind must be one of consul service kind or empty
What it means
validateConsulService checks that the service's `kind` field maps to a valid Consul service kind (typical, api-gateway, ingress-gateway, mesh-gateway, terminating-gateway) or is empty. Any other kind value is rejected because Consul would not accept the registration.
Source
Thrown at nomad/structs/services.go:883
mErr.Errors = append(mErr.Errors, fmt.Errorf("Check %s invalid: tcp checks are not valid for Connect enabled services", c.Name))
continue
}
// validate the consul check
if err := c.validateConsul(); err != nil {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Check %s invalid: %v", c.Name, err))
}
}
// validate the consul service kind
switch api.ServiceKind(s.Kind) {
case api.ServiceKindTypical,
api.ServiceKindAPIGateway,
api.ServiceKindIngressGateway,
api.ServiceKindMeshGateway,
api.ServiceKindTerminatingGateway:
default:
mErr.Errors = append(mErr.Errors, fmt.Errorf("Service %s kind must be one of consul service kind or empty", s.Name))
}
// check connect
if s.Connect != nil {
if err := s.Connect.Validate(); err != nil {
mErr.Errors = append(mErr.Errors, err)
}
// if service is connect native, service task must be set (which may
// happen implicitly in a job mutation if there is only one task)
if s.Connect.IsNative() && len(s.TaskName) == 0 {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Service %s is Connect Native and requires setting the task", s.Name))
}
// if service is connect native a port must be set on the service or consul will reject it
if s.Connect.IsNative() && s.PortLabel == "" {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Service %s is Connect Native and requires setting the port", s.Name))
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove the kind field (empty/typical is the default for normal services).
- Use one of the supported gateway kinds: "api-gateway", "ingress-gateway", "mesh-gateway", or "terminating-gateway".
- Fix the casing/spelling of the kind value.
Example fix
// before
service {
name = "ingress"
kind = "ingress_gateway"
gateway { ingress { ... } }
}
// after
service {
name = "ingress"
kind = "ingress-gateway"
gateway { ingress { ... } }
} Defensive patterns
Strategy: validation
Validate before calling
var validKinds = map[string]bool{"": true, "typical": true, "api-gateway": true, "ingress-gateway": true, "mesh-gateway": true, "terminating-gateway": true}
if !validKinds[svc.Kind] { return fmt.Errorf("invalid kind %q", svc.Kind) } Prevention
- Omit kind for normal services; only set it for gateway services
- Copy kind values exactly from Nomad docs (hyphenated, lowercase)
- Add a schema lint for allowed kind values in your job repo
When it happens
Trigger: Setting kind = "connect-proxy", "terminating-gateway " (typo/whitespace), or any invented kind string on a service stanza with provider = "consul".
Common situations: Hand-copying Consul catalog kinds that Nomad services don't support; typos in gateway kind names; using kinds reserved for Consul's own registrations.
Related errors
- expose may only be set for Consul service checks
- on_update may only be set to ignore_warnings for Consul serv
- ignore_warnings on check_restart only supported for Consul s
- address_mode = driver may only be set for Consul service che
- success_before_passing may only be set for Consul service ch
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f63208cca3ef6c2c.
Report an issue: GitHub.