hashicorp/nomad · error

unable to get address for service %q: %v

Error message

unable to get address for service %q: %v

What it means

generateNomadServiceRegistration in the Nomad service registration provider wraps any error from serviceregistration.GetAddress with this message naming the service. It is a wrapper: the root cause is one of the GetAddress failures (missing network status, bad port label, invalid mode, etc.), surfaced during RegisterWorkload.

Source

Thrown at client/serviceregistration/nsd/nsd.go:376

func (s *ServiceRegistrationHandler) Shutdown() { close(s.shutDownCh) }

// generateNomadServiceRegistration is a helper to build the Nomad specific
// registration object on a per-service basis.
func (s *ServiceRegistrationHandler) generateNomadServiceRegistration(
	serviceSpec *structs.Service, workload *serviceregistration.WorkloadServices) (*structs.ServiceRegistration, error) {

	// Service address modes default to auto.
	addrMode := serviceSpec.AddressMode
	if addrMode == "" {
		addrMode = structs.AddressModeAuto
	}

	// Determine the address to advertise based on the mode.
	ip, port, err := serviceregistration.GetAddress(
		serviceSpec.Address, addrMode, serviceSpec.PortLabel, workload.Networks,
		workload.DriverNetwork, workload.Ports, workload.NetworkStatus)
	if err != nil {
		return nil, fmt.Errorf("unable to get address for service %q: %v", serviceSpec.Name, err)
	}

	// Build the tags to use for this registration which is a result of whether
	// this is a canary, or not.
	var tags []string

	if workload.Canary && len(serviceSpec.CanaryTags) > 0 {
		tags = make([]string, len(serviceSpec.CanaryTags))
		copy(tags, serviceSpec.CanaryTags)
	} else {
		tags = make([]string, len(serviceSpec.Tags))
		copy(tags, serviceSpec.Tags)
	}

	return &structs.ServiceRegistration{
		ID:          serviceregistration.MakeAllocServiceID(workload.AllocInfo.AllocID, workload.Name(), serviceSpec),
		ServiceName: serviceSpec.Name,
		NodeID:      s.cfg.NodeID,

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the wrapped %v cause to identify which GetAddress condition failed
  2. Fix the service's port label to a declared port or positive numeric literal
  3. Set a valid address_mode (host/driver/alloc) and ensure network status is available for alloc mode
  4. Check workload.Networks/DriverNetwork/Ports/NetworkStatus inputs are populated as expected for the driver

Example fix

// before
service {
  name = "api"
  port = "admin"
}
// after
service {
  name = "api"
  port = "http"
}
Defensive patterns

Strategy: try-catch

Validate before calling

if err := validateServiceAddressing(serviceSpec, workload); err != nil {
    return nil, fmt.Errorf("service %q pre-check failed: %w", serviceSpec.Name, err)
}

Type guard

func addressResolvable(spec ServiceSpec, w Workload) bool {
    return !(spec.AddressMode == "alloc" && w.NetworkStatus == nil) &&
        (isNumericLiteral(spec.PortLabel) || portLabelExists(spec.PortLabel, w.Ports))
}

Try / catch

reg, err := provider.RegisterWorkload(workload)
if err != nil {
    var svcName string
    if m := regexp.MustCompile(`service "([^"]+)"`).FindStringSubmatch(err.Error()); m != nil {
        svcName = m[1]
    }
    logger.Error("nomad service registration failed", "service", svcName, "err", err)
    return err
}

Prevention

When it happens

Trigger: RegisterWorkload calls generateNomadServiceRegistration for a Nomad-provider service; GetAddress fails for that service spec (nil NetworkStatus with alloc mode, unknown/non-numeric port label, <=0 literal port, or unknown address mode), and the error is re-wrapped with the service name.

Common situations: Group/task service stanzas with misconfigured port or address_mode being registered at task start/update; checking client logs after a service registration failure and needing the wrapped inner error to diagnose.

Related errors


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