hashicorp/nomad · error

check cannot use address_mode="alloc_ipv6", only checks…

Error message

check %q cannot use address_mode="alloc_ipv6", only checks defined in a "group" service block can use this mode

What it means

The IPv6 counterpart for checks: address_mode="alloc_ipv6" on a check is only valid when the check belongs to a service declared in a "group" block. Task-level checks cannot claim the allocation's IPv6 address, so validation rejects it, attributing the error to the parent service name.

Solutions

  1. Move the parent service (with the check) to the group level.
  2. Remove or change the check's address_mode to "driver" or "host".
  3. Validate the job locally with `nomad job validate` before submitting.

Example fix

// before
task "app" {
  service {
    name = "api"
    check { name = "live"; address_mode = "alloc_ipv6"; port = "8080" }
  }
}

// after
group "web" {
  service {
    name = "api"
    check { name = "live"; address_mode = "alloc_ipv6"; port = "8080" }
  }
  task "app" { }
}
Defensive patterns

Strategy: validation

Validate before calling

for taskLevelChecks {
  if c.AddressMode == "alloc_ipv6" {
    return fmt.Errorf("check %q: alloc_ipv6 address_mode requires a group-level service", c.Name)
  }
}

Prevention

When it happens

Trigger: Submitting a job with check.address_mode = "alloc_ipv6" (AddressModeAllocIPv6) inside a task-level service.

Common situations: Configuring IPv6 health checks after copying group-level check stanzas into task-level services; cluster-wide IPv6 migration where address modes were added indiscriminately.

Related errors


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

Appendix: source

Thrown at nomad/structs/structs.go:8531

		// connect block is only allowed on group level
		if service.Connect != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("service %q cannot have \"connect\" block, only services defined in a \"group\" block can", service.Name))
		}

		// Ensure that check names are unique and have valid ports
		knownChecks := make(map[string]struct{})
		for _, check := range service.Checks {
			if _, ok := knownChecks[check.Name]; ok {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("check %q is duplicate", check.Name))
			}
			knownChecks[check.Name] = struct{}{}

			if check.AddressMode == AddressModeAlloc {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("check %q cannot use address_mode=\"alloc\", only checks defined in a \"group\" service block can use this mode", service.Name))
			}

			if check.AddressMode == AddressModeAllocIPv6 {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("check %q cannot use address_mode=\"alloc_ipv6\", only checks defined in a \"group\" service block can use this mode", service.Name))
			}

			if !check.RequiresPort() {
				// No need to continue validating check if it doesn't need a port
				continue
			}

			effectivePort := check.PortLabel
			if effectivePort == "" {
				// Inherits from service
				effectivePort = service.PortLabel
			}

			if effectivePort == "" {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("check %q is missing a port", check.Name))
				continue
			}

View on GitHub (pinned to 482b49bf1a)