hashicorp/nomad · error

Consul Connect services %q and %q in group %q using same add

Error message

Consul Connect services %q and %q in group %q using same address for upstreams (%s)

What it means

Nomad's connect job validation hook (`groupConnectUpstreamsValidate`) builds a listener string (host:port or unix socket path) for every Consul Connect upstream in a task group and rejects duplicates. Two Connect services in the same group declare upstreams that would bind to the exact same local address, so the second would fail at runtime; the job mutator/validator throws this error at `nomad job run`/plan time instead.

Source

Thrown at nomad/job_endpoint_hook_connect.go:587

	listeners := make(map[string]string) // address or path-> service

	var connectBlockCount int
	var hasTproxy bool

	for _, service := range services {
		if service.Connect != nil {
			connectBlockCount++
		}
		if service.Connect.HasSidecar() && service.Connect.SidecarService.Proxy != nil {
			for _, up := range service.Connect.SidecarService.Proxy.Upstreams {
				var listener string
				if up.LocalBindSocketPath == "" {
					listener = net.JoinHostPort(up.LocalBindAddress, strconv.Itoa(up.LocalBindPort))
				} else {
					listener = up.LocalBindSocketPath
				}
				if s, exists := listeners[listener]; exists {
					return fmt.Errorf(
						"Consul Connect services %q and %q in group %q using same address for upstreams (%s)",
						service.Name, s, g.Name, listener,
					)
				}
				listeners[listener] = service.Name
			}

			if tp := service.Connect.SidecarService.Proxy.TransparentProxy; tp != nil {
				hasTproxy = true
				for _, net := range g.Networks {
					if !net.DNS.IsZero() && !tp.NoDNS {
						return fmt.Errorf(
							"Consul Connect transparent proxy cannot be used with network.dns unless no_dns=true")
					}
				}
				for _, portLabel := range tp.ExcludeInboundPorts {
					if !transparentProxyPortLabelValidate(g, portLabel) {
						return fmt.Errorf(

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Give each upstream a distinct local bind port: set `upstream { local_bind_port = <unique-port> }` on one of the conflicting upstreams.
  2. If both upstreams target the same destination service, remove the duplicate upstream and reference the service once.
  3. Use distinct `local_bind_socket_path` values if you bind upstreams via unix sockets instead of TCP.
  4. Keep the default bind address but vary ports, or set a unique `local_bind_address` per upstream.

Example fix

// before
upstream {
  destination_name = "count-api"
}
upstream {
  destination_name = "count-api2"
  # local_bind_port defaults to 8443 too -> collision
}
// after
upstream {
  destination_name = "count-api"
}
upstream {
  destination_name = "count-api2"
  local_bind_port  = 9191
}
Defensive patterns

Strategy: validation

Validate before calling

// Before submitting, ensure every upstream in each group has a unique bind point.
function validateUpstreamBinds(groups) {
  for (const g of groups) {
    const seen = new Map();
    for (const svc of g.services.filter(s => s.connect)) {
      for (const up of svc.connect.sidecar_service?.proxy?.upstreams ?? svc.connect.sidecar_service?.upstreams ?? []) {
        const listener = up.local_bind_socket_path ?? `${up.local_bind_address ?? '127.0.0.1'}:${up.local_bind_port ?? 8443}`;
        if (seen.has(listener)) throw new Error(`duplicate upstream bind ${listener} in group ${g.name}`);
        seen.set(listener, svc.name);
      }
    }
  }
}

Prevention

When it happens

Trigger: Submit a job (nomad job run/plan/validate, or the jobs API Validate endpoint) where a task group contains two `service { connect {} }` blocks whose `upstream` blocks resolve to the identical LocalBindAddress:LocalBindPort or LocalBindSocketPath. This fires in groupConnectUpstreamsValidate when `listeners[listener]` already contains the listener string.

Common situations: Copy-pasting upstream blocks and forgetting to change the default local bind port (8443 or the service port); two upstreams to the same destination service declared under different service blocks, both using the default local bind address; groups with many connect services where each upstream reuses the socket path.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/5d1010c44bb8645d. Report an issue: GitHub.