hashicorp/nomad · error

'port_map' cannot map group network ports, use 'ports' inste

Error message

'port_map' cannot map group network ports, use 'ports' instead

What it means

port_map is the legacy Docker-driver mechanism for mapping static network ports from the old single-task network model. It cannot be used with the newer group network block that produces task.Resources.Ports. If a job mixes a group network with port_map, the driver rejects it and directs users to the ports option.

Source

Thrown at drivers/docker/driver.go:1450

			} else {
				return c, fmt.Errorf("Port %q not found, check network block", port)
			}
		}
	case len(task.Resources.NomadResources.Networks) > 0:
		network := task.Resources.NomadResources.Networks[0]

		for _, port := range network.ReservedPorts {
			ports.addMapped(port.Label, network.IP, port.Value, driverConfig.PortMap)
		}

		for _, port := range network.DynamicPorts {
			ports.addMapped(port.Label, network.IP, port.Value, driverConfig.PortMap)
		}

	default:
		if len(driverConfig.PortMap) > 0 {
			if task.Resources.Ports != nil {
				return c, fmt.Errorf("'port_map' cannot map group network ports, use 'ports' instead")
			}
			return c, fmt.Errorf("Trying to map ports but no network interface is available")
		}
	}
	hostConfig.PortBindings = make(networkapi.PortMap, len(ports.publishedPorts))
	for port, bindings := range ports.publishedPorts {
		parsedPort := networkapi.MustParsePort(string(port))
		convertedBindings := make([]networkapi.PortBinding, len(bindings))
		for i, binding := range bindings {
			convertedBinding := networkapi.PortBinding{
				HostPort: binding.HostPort,
			}
			if binding.HostIP != "" {
				convertedBinding.HostIP = netip.MustParseAddr(binding.HostIP)
			}
			convertedBindings[i] = convertedBinding
		}
		hostConfig.PortBindings[parsedPort] = convertedBindings

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Replace port_map with ports = ["label1", "label2"] referencing group network port labels
  2. Delete the port_map stanza if group network ports already define the mapping
  3. Split legacy task-level network stanzas into group network blocks with named ports

Example fix

// before
driver {
  docker {
    port_map { http = 8080 }
  }
}
// after
driver {
  docker {
    ports = ["http"]
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if len(cfg.PortMap) > 0 && groupHasNetworkBlock {
  return errors.New("use ports = [...] with group networks, not port_map")
}

Try / catch

err := client.StartTask(task); if err != nil && strings.Contains(err.Error(), "cannot map group network ports") { migratePortMapToPorts(cfg) }

Prevention

When it happens

Trigger: StartTask -> createContainerConfig reaches the default port-resolution branch with len(driverConfig.PortMap) > 0 and task.Resources.Ports != nil (a group network block exists), so port_map and ports/group networking collide.

Common situations: Upgrading jobs written for old Nomad task-level networks to group networks while keeping port_map; combining examples from old blog posts with current Nomad job specs.

Related errors


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