kubernetes/kops · error

failed to find load-balancer %q public address

Error message

failed to find load-balancer %q public address

What it means

In the kOps Hetzner load-balancer task's FindAddresses, once the matching hcloud load balancer is found by name, the task requires its public IPv4 address. This error is thrown when the load balancer exists but loadbalancer.PublicNet.IPv4.IP is nil, meaning Hetzner reports no public IPv4 assigned to it.

Source

Thrown at upup/pkg/fi/cloudup/hetznertasks/loadbalancer.go:90

	if strings.HasPrefix(c.T.ClusterConfigBase.Path(), "memfs://tests/") {
		return nil, nil
	}

	ctx := context.TODO()
	cloud := c.T.Cloud.(hetzner.HetznerCloud)
	client := cloud.LoadBalancerClient()

	// TODO(hakman): Find using label selector
	loadbalancers, err := client.All(ctx)
	if err != nil {
		return nil, err
	}

	for _, loadbalancer := range loadbalancers {
		if loadbalancer.Name == fi.ValueOf(v.Name) {
			var addresses []string
			if loadbalancer.PublicNet.IPv4.IP == nil {
				return nil, fmt.Errorf("failed to find load-balancer %q public address", fi.ValueOf(v.Name))
			}
			addresses = append(addresses, loadbalancer.PublicNet.IPv4.IP.String())
			for _, privateNetwork := range loadbalancer.PrivateNet {
				if privateNetwork.IP == nil {
					return nil, fmt.Errorf("failed to find load-balancer %q private address", fi.ValueOf(v.Name))
				}
				addresses = append(addresses, privateNetwork.IP.String())
			}
			return addresses, nil
		}
	}

	return nil, nil
}

func (v *LoadBalancer) Find(c *fi.CloudupContext) (*LoadBalancer, error) {
	ctx := context.TODO()
	cloud := c.T.Cloud.(hetzner.HetznerCloud)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the load balancer in the Hetzner console/API and ensure a public IPv4 is assigned to it; recreate the load balancer via kOps if the public interface was disabled.
  2. Wait for/probe the load balancer creation action to finish (WatchProgress) before FindAddresses runs, then re-run kops update/apply.
  3. Align the cluster spec: if the LB is intentionally private-only, configure the kOps API endpoint/Ingress to use the private address path instead of relying on FindAddresses public output.
Defensive patterns

Strategy: validation

Validate before calling

lb, _, err := client.Get(ctx, lbName)
if err != nil {
    return err
}
if lb != nil && lb.PublicNet.IPv4.IP == nil {
    return fmt.Errorf("load balancer %s has no public IPv4 yet; wait for creation to finish", lbName)
}

Type guard

func hasPublicIPv4(lb *hcloud.LoadBalancer) bool {
    return lb != nil && lb.PublicNet.IPv4.IP != nil
}

Prevention

When it happens

Trigger: client.All() returned the load balancer whose name matches the task, but its PublicNet.IPv4.IP is nil — typically because the load balancer was created without a public interface or the public IP allocation has not completed / was disabled.

Common situations: Load balancer created manually or by an older tooling version without public IPv4; Hetzner API returns the LB mid-provision before the IP is attached; kOps cluster spec expects a public API endpoint but the LB is private-only.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/05431d8e426c5724. Report an issue: GitHub.