hashicorp/nomad · error
service %q cannot use address_mode="alloc_ipv6", only servic
Error message
service %q cannot use address_mode="alloc_ipv6", only services defined in a "group" block can use this mode
What it means
Same constraint as address_mode="alloc" but for the IPv6 variant: address_mode="alloc_ipv6" is only permitted on services declared directly in a "group" block. Task-level services cannot claim the allocation's IPv6 address because the address belongs to the allocation, not to an individual task's network namespace. Thrown during Job.Register validation and accumulated in the MultiError.
Source
Thrown at nomad/structs/structs.go:8490
addServicePort := func(label, service string) {
if _, ok := servicePorts[label]; !ok {
servicePorts[label] = map[string]struct{}{}
}
servicePorts[label][service] = struct{}{}
}
knownServices := make(map[string]struct{})
for i, service := range t.Services {
if err := service.Validate(); err != nil {
outer := fmt.Errorf("service[%d] %+q validation failed: %s", i, service.Name, err)
mErr.Errors = append(mErr.Errors, outer)
}
if service.AddressMode == AddressModeAlloc {
mErr.Errors = append(mErr.Errors, fmt.Errorf("service %q cannot use address_mode=\"alloc\", only services defined in a \"group\" block can use this mode", service.Name))
}
if service.AddressMode == AddressModeAllocIPv6 {
mErr.Errors = append(mErr.Errors, fmt.Errorf("service %q cannot use address_mode=\"alloc_ipv6\", only services defined in a \"group\" block can use this mode", service.Name))
}
// Ensure that services with the same name are not being registered for
// the same port
if _, ok := knownServices[service.Name+service.PortLabel]; ok {
mErr.Errors = append(mErr.Errors, fmt.Errorf("service %q is duplicate", service.Name))
}
knownServices[service.Name+service.PortLabel] = struct{}{}
if service.PortLabel != "" {
if service.AddressMode == "driver" {
// Numeric port labels are valid for address_mode=driver
_, err := strconv.Atoi(service.PortLabel)
if err != nil {
// Not a numeric port label, add it to list to check
addServicePort(service.PortLabel, service.Name)
}
} else {View on GitHub (pinned to 482b49bf1a)
Solutions
- Move the service block from the `task` to the `group` level so alloc_ipv6 is legal.
- Remove `address_mode = "alloc_ipv6"` from the task-level service and rely on the default driver mode.
- Use `nomad job validate` locally to catch the misplacement before submitting.
Example fix
// before
task "app" {
service {
name = "svc6"
address_mode = "alloc_ipv6"
}
}
// after
group "web" {
service {
name = "svc6"
address_mode = "alloc_ipv6"
}
task "app" { }
} Defensive patterns
Strategy: validation
Validate before calling
for _, tg := range job.TaskGroups {
for _, t := range tg.Tasks {
for _, s := range t.Services {
if s.AddressMode == "alloc_ipv6" {
return fmt.Errorf("service %q: move alloc_ipv6 to group level", s.Name)
}
}
}
} Prevention
- Keep alloc_ipv6 services at group level only
- Lint job files for address_mode usage inside task stanzas
- Validate jobs with `nomad job validate` as a pre-submit gate
When it happens
Trigger: Submitting a job where a service nested inside a `task` block sets `address_mode = "alloc_ipv6"` (AddressModeAllocIPv6).
Common situations: Configuring IPv6-only clusters and copy-pasting group service stanzas into tasks; experimenting with IPv6 address advertisement at the wrong nesting level.
Related errors
- service %q cannot use address_mode="alloc", only services de
- check %q cannot use address_mode="alloc", only checks define
- check %q cannot use address_mode="alloc_ipv6", only checks d
- address_mode = driver may only be set for Consul service che
- invalid bridge_network_subnet: not an IPv4 address: %s
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/899d9d7a888890dd.
Report an issue: GitHub.