hashicorp/nomad · error
%s: %w: group %q has %d networks
Error message
%s: %w: group %q has %d networks
What it means
Nomad's connect validation requires each task group using Consul Connect (sidecar, gateway, or expose checks) to declare exactly one group network block. The job submission is rejected when the group has zero or more than one network. This invariant exists because connect sidecars/gateways are attached to a single group network namespace and Nomad cannot pick which network block applies.
Source
Thrown at nomad/job_endpoint_hook_connect.go:636
func transparentProxyPortLabelValidate(g *structs.TaskGroup, portLabel string) bool {
if _, err := strconv.ParseUint(portLabel, 10, 16); err == nil {
return true
}
for _, network := range g.Networks {
for _, reservedPort := range network.ReservedPorts {
if reservedPort.Label == portLabel {
return true
}
}
}
return false
}
func groupConnectNetworkModeValidate(g *structs.TaskGroup, errorPrefix string, allowHost bool) error {
if nn := len(g.Networks); nn != 1 {
return fmt.Errorf("%s: %w: group %q has %d networks",
errorPrefix, ErrConnectRequireOneNetwork, g.Name, nn)
}
mode := g.Networks[0].Mode
if mode == "bridge" || (allowHost && mode == "host") || strings.HasPrefix(mode, "cni/") {
return nil
}
// helpful error message
allowed := `"bridge" or "cni/*"`
if allowHost {
allowed = `"bridge", "host", or "cni/*"`
}
return fmt.Errorf("%s: %w: group %q uses network mode %q; must be %s",
errorPrefix, ErrConnectInvalidNetworkMode, g.Name, mode, allowed)
}
func groupConnectSidecarValidate(g *structs.TaskGroup, s *structs.Service) error {View on GitHub (pinned to 482b49bf1a)
Solutions
- Ensure the task group has exactly one group-level `network` block, moving any ports into that single block.
- Remove duplicate network blocks by merging their port/dns settings into one stanza.
- If the group does not need connect, remove the connect sidecar service/gateway config so validation is skipped.
Example fix
// before
group "api" {
network {
port "http" {}
}
network {
port "metrics" {}
}
service {
name = "api"
connect { sidecar_service {} }
}
}
// after
group "api" {
network {
port "http" {}
port "metrics" {}
}
service {
name = "api"
connect { sidecar_service {} }
}
} Defensive patterns
Strategy: validation
Validate before calling
function validateConnectGroupNetworks(group) {
const nets = (group.networks || []);
if (nets.length !== 1) {
throw new Error(`group "${group.name}" has ${nets.length} networks; connect groups need exactly one`);
}
} Type guard
function hasExactlyOneNetwork(g) { return Array.isArray(g.networks) && g.networks.length === 1; } Prevention
- Keep exactly one group-level network block per connect-enabled group; put all ports in it.
- Validate job files with `nomad job validate` before submit in CI.
- Only add connect sidecar services to groups that already declare a bridge network.
When it happens
Trigger: Submitting a job where a task group with a connect sidecar service (or gateway, or expose block) has no `network {}` block, or has two or more `network {}` blocks at the group level; groupConnectNetworkModeValidate returns this immediately on `len(g.Networks) != 1`.
Common situations: Jobs converted from pre-connect templates missing the group network stanza; users adding a second network block for an extra port or DNS setting on a connect-enabled group; merging partial HCL that appends networks; programmatically generated jobs appending networks per service.
Related errors
- ErrConnectRequireOneNetwork
- ErrConnectInvalidNetworkMode
- service.port must be set for mesh gateway service
- %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/cbfa6393da00d987.
Report an issue: GitHub.