hashicorp/nomad · error

Port label %s already in use by %s

Error message

Port label %s already in use by %s

What it means

Raised by TaskGroup.validateNetworks when two port entries in the task group's network stanzas share the same label. Nomad tracks port labels in a map; if a label is already claimed ('taskgroup network' by default), the duplicate is rejected so that port-label references (services, checks, connect) stay unambiguous.

Source

Thrown at nomad/structs/structs.go:7337

			outer := fmt.Errorf("Task %s validation failed: %v", task.Name, err)
			mErr = multierror.Append(mErr, outer)
		}
	}

	return mErr.ErrorOrNil()
}

func (tg *TaskGroup) validateNetworks() error {
	var mErr multierror.Error
	portLabels := make(map[string]string)
	// host_network -> static port tracking
	staticPortsIndex := make(map[string]map[int]string)
	cniArgKeys := set.New[string](len(tg.Networks))

	for _, net := range tg.Networks {
		for _, port := range append(net.ReservedPorts, net.DynamicPorts...) {
			if other, ok := portLabels[port.Label]; ok {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("Port label %s already in use by %s", port.Label, other))
			} else {
				portLabels[port.Label] = "taskgroup network"
			}

			if port.Value != 0 {
				hostNetwork := port.HostNetwork
				if hostNetwork == "" {
					hostNetwork = "default"
				}
				staticPorts, ok := staticPortsIndex[hostNetwork]
				if !ok {
					staticPorts = make(map[int]string)
				}
				// static port
				if other, ok := staticPorts[port.Value]; ok {
					if !port.IgnoreCollision {
						err := fmt.Errorf("Static port %d already reserved by %s", port.Value, other)
						mErr.Errors = append(mErr.Errors, err)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Search the task group's network blocks for the duplicated label named in the error
  2. Rename one of the duplicate port labels and update any services/tasks referencing it
  3. Remove redundant port entries if they were accidentally duplicated by templating/merge
  4. Run `nomad job validate` after editing to confirm all labels are unique

Example fix

// before
network {
  port "http" {}
  port "http" {}
}
// after
network {
  port "http" {}
  port "metrics" {}
}
Defensive patterns

Strategy: validation

Validate before calling

func uniquePortLabels(tg *api.TaskGroup) error {
  seen := map[string]bool{}
  for _, n := range tg.Networks {
    for _, p := range append(n.ReservedPorts, n.DynamicPorts...) {
      if seen[p.Label] { return fmt.Errorf("port label %q duplicated in group %s", p.Label, *tg.Name) }
      seen[p.Label] = true
    }
  }
  return nil
}

Type guard

func hasUniquePortLabels(tg *api.TaskGroup) bool {
  seen := map[string]bool{}
  for _, n := range tg.Networks {
    for _, p := range append(n.ReservedPorts, n.DynamicPorts...) {
      if seen[p.Label] { return false }
      seen[p.Label] = true
    }
  }
  return true
}

Prevention

When it happens

Trigger: A job whose `network { port "http" {} }` (or ReservedPorts/DynamicPorts entries) defines the same port label twice — either within one network block or across multiple network blocks in the same task group.

Common situations: Merging job files or template snippets that each define common labels like "http"/"metrics"; auto-generated specs appending a network stanza when one already exists; copy-pasting a network block into a group that already has ports.

Related errors


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