hashicorp/nomad · error
Check %s invalid: check requires a port but neither check no
Error message
Check %s invalid: check requires a port but neither check nor service %+q have a port
What it means
validateCheckPort fails when a service check RequiresPort() (e.g. tcp, http, grpc checks) but neither the check nor its parent service declares a port. Nomad cannot know which port to probe, so the service definition is rejected. Connect-based checks (which target the proxy) are exempt because they don't need an address.
Source
Thrown at nomad/structs/services.go:845
// identity name and service name.
func (s *Service) IdentityHandle(replace envReplacer) *WIHandle {
if s.Identity != nil {
wi := &WIHandle{
IdentityName: s.Identity.Name,
WorkloadIdentifier: s.Name,
WorkloadType: WorkloadTypeService,
}
if replace != nil {
wi.InterpolatedWorkloadIdentifier = replace(s.Name)
}
return wi
}
return nil
}
func (s *Service) validateCheckPort(c *ServiceCheck) error {
if s.PortLabel == "" && c.PortLabel == "" && c.RequiresPort() {
return fmt.Errorf("Check %s invalid: check requires a port but neither check nor service %+q have a port", c.Name, s.Name)
}
return nil
}
// validateConsulService performs validation on a service which is using the
// consul provider.
func (s *Service) validateConsulService(mErr *multierror.Error) {
// check checks
for _, c := range s.Checks {
// validate the check port
if err := s.validateCheckPort(c); err != nil {
mErr.Errors = append(mErr.Errors, err)
continue
}
// TCP checks against a Consul Connect enabled service are not supported
// due to the service being bound to the loopback interface inside the
// network namespaceView on GitHub (pinned to 482b49bf1a)
Solutions
- Set `port` on the check stanza (e.g. port = "http").
- Set `port` on the parent service stanza so checks inherit it.
- If the check targets a Connect sidecar (http/grpc to the proxy), configure it so RequiresPort() is false rather than adding a port.
Example fix
// before
service {
name = "web"
check {
type = "tcp"
interval = "10s"
timeout = "2s"
}
}
// after
service {
name = "web"
port = "http"
check {
type = "tcp"
interval = "10s"
timeout = "2s"
}
} Defensive patterns
Strategy: validation
Validate before calling
func checkHasPort(svcPort string, c Check) error {
needsPort := c.Type == "tcp" || c.Type == "http" || c.Type == "grpc"
if needsPort && svcPort == "" && c.PortLabel == "" {
return fmt.Errorf("check %q needs a port on the check or service", c.Name)
}
return nil
} Prevention
- Always define a port label on services that have tcp/http/grpc checks
- Prefer setting port at the service level so all checks inherit it
- Lint job files with `nomad job validate` in CI
When it happens
Trigger: A service with an empty port label containing a check of type tcp/http/grpc with no check-level port; or a check whose port refers to nothing because the service's port label is empty.
Common situations: Defining a health check on a service without assigning a port label; refactoring a service and dropping the port field; templated jobs where the port variable is empty.
Related errors
- expose may only be set for Consul service checks
- on_update may only be set to ignore_warnings for Consul serv
- success_before_passing may only be set for Consul service ch
- failures_before_critical may only be set for Consul service
- failures_before_warning may only be set for Consul service c
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/9452adb33fe8b8b5.
Report an issue: GitHub.