hashicorp/nomad · error
service.port must be set for mesh gateway service
Error message
service.port must be set for mesh gateway service
What it means
A Consul mesh gateway service requires a service port label because that port is used to publish the mesh gateway's WAN address. Nomad's groupConnectHook mutator returns this error when a connect gateway of kind mesh-gateway has an empty service.PortLabel.
Source
Thrown at nomad/job_endpoint_hook_connect.go:363
service.Connect.Gateway.Proxy = gatewayProxy(service.Connect.Gateway, netMode)
// Inject a port whether bridge or host network (if not already set).
// This port is accessed by the magic of Connect plumbing so it seems
// reasonable to keep the magic alive here.
if service.Connect.IsTerminating() && service.PortLabel == "" {
// Inject a dynamic port for the terminating gateway.
portLabel := envoy.PortLabel(structs.ConnectTerminatingPrefix, service.Name, "")
service.PortLabel = portLabel
injectPort(g, portLabel)
}
// A mesh Gateway will need 2 ports (lan and wan).
if service.Connect.IsMesh() {
// service port is used for mesh gateway wan address - it should
// come from a configured host_network to make sense
if service.PortLabel == "" {
return errors.New("service.port must be set for mesh gateway service")
}
// Inject a dynamic port for mesh gateway LAN address.
lanPortLabel := envoy.PortLabel(structs.ConnectMeshPrefix, service.Name, "lan")
injectPort(g, lanPortLabel)
}
// inject the gateway task only if it does not yet already exist
if !hasGatewayTaskForService(g, service.Name) {
prefix := service.Connect.Gateway.Prefix()
// detect whether the group is in host networking mode, which will
// require tweaking the default gateway task config
netHost := netMode == "host"
customizedTLS := service.Connect.IsCustomizedTLS()
task := newConnectGatewayTask(prefix, service.Name,
service.GetConsulClusterName(g), groupConnectGuessTaskDriver(g), netHost, customizedTLS)View on GitHub (pinned to 482b49bf1a)
Solutions
- Set `port` on the service that has the mesh gateway block (e.g. pointing to a port on a configured host_network).
- Use a port defined with host_network so the WAN address is meaningful.
- Re-submit the job after adding the port label.
Example fix
// before
service {
name = "mesh-gw"
connect {
gateway {
mesh {}
}
}
}
// after
service {
name = "mesh-gw"
port = "8443"
connect {
gateway {
mesh {}
}
}
} Defensive patterns
Strategy: validation
Validate before calling
for _, svc := range group.Services {
if svc.Connect != nil && svc.Connect.IsMesh() && svc.PortLabel == "" {
return fmt.Errorf("service %q: mesh gateway requires a port", svc.Name)
}
} Prevention
- Always set service.port for mesh gateways
- Back the port with a host_network for a meaningful WAN address
- Compare with ingress/terminating gateway examples, which differ
When it happens
Trigger: Defining a `gateway { mesh { ... } }` in a connect block without setting the service's `port` field, then submitting/mutating the job through groupConnectHook.
Common situations: Configuring Consul ingress/terminating gateways works without a service port, so users assume mesh gateways do too; forgetting that mesh gateways additionally need the wan-facing port label.
Related errors
- ErrConnectRequireOneNetwork
- ErrConnectInvalidNetworkMode
- %s: %w: group %q has %d networks
- %s: %w: group %q uses network mode %q; must be %s
- Consul Connect service name %q in group %q must not contain
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/aea61ea17b0472fb.
Report an issue: GitHub.