{"record":{"id":"cbfa6393da00d987","repo":"hashicorp/nomad","slug":"s-w-group-q-has-d-networks","errorCode":null,"errorMessage":"%s: %w: group %q has %d networks","messagePattern":"(.+?): %w: group %q has (.+?) networks","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/job_endpoint_hook_connect.go","lineNumber":636,"sourceCode":"\nfunc transparentProxyPortLabelValidate(g *structs.TaskGroup, portLabel string) bool {\n\tif _, err := strconv.ParseUint(portLabel, 10, 16); err == nil {\n\t\treturn true\n\t}\n\n\tfor _, network := range g.Networks {\n\t\tfor _, reservedPort := range network.ReservedPorts {\n\t\t\tif reservedPort.Label == portLabel {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\nfunc groupConnectNetworkModeValidate(g *structs.TaskGroup, errorPrefix string, allowHost bool) error {\n\tif nn := len(g.Networks); nn != 1 {\n\t\treturn fmt.Errorf(\"%s: %w: group %q has %d networks\",\n\t\t\terrorPrefix, ErrConnectRequireOneNetwork, g.Name, nn)\n\t}\n\n\tmode := g.Networks[0].Mode\n\tif mode == \"bridge\" || (allowHost && mode == \"host\") || strings.HasPrefix(mode, \"cni/\") {\n\t\treturn nil\n\t}\n\n\t// helpful error message\n\tallowed := `\"bridge\" or \"cni/*\"`\n\tif allowHost {\n\t\tallowed = `\"bridge\", \"host\", or \"cni/*\"`\n\t}\n\treturn fmt.Errorf(\"%s: %w: group %q uses network mode %q; must be %s\",\n\t\terrorPrefix, ErrConnectInvalidNetworkMode, g.Name, mode, allowed)\n}\n\nfunc groupConnectSidecarValidate(g *structs.TaskGroup, s *structs.Service) error {","sourceCodeStart":618,"sourceCodeEnd":654,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint_hook_connect.go#L618-L654","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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.","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."],"exampleFix":"// before\ngroup \"api\" {\n  network {\n    port \"http\" {}\n  }\n  network {\n    port \"metrics\" {}\n  }\n  service {\n    name = \"api\"\n    connect { sidecar_service {} }\n  }\n}\n// after\ngroup \"api\" {\n  network {\n    port \"http\" {}\n    port \"metrics\" {}\n  }\n  service {\n    name = \"api\"\n    connect { sidecar_service {} }\n  }\n}","handlingStrategy":"validation","validationCode":"function validateConnectGroupNetworks(group) {\n  const nets = (group.networks || []);\n  if (nets.length !== 1) {\n    throw new Error(`group \"${group.name}\" has ${nets.length} networks; connect groups need exactly one`);\n  }\n}","typeGuard":"function hasExactlyOneNetwork(g) { return Array.isArray(g.networks) && g.networks.length === 1; }","tryCatchPattern":null,"preventionTips":["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."],"tags":["nomad","consul-connect","job-validation","network"],"backgroundTag":"connect-network-count-invalid","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}