kubernetes/kops · error
failed to find network for loadbalancer
Error message
failed to find network for loadbalancer %q
What it means
In RenderHetzner, when creating a NEW load balancer (a == nil), the task requires e.Network (the Hetzner network the LB should join) because the create call passes a network ID and targets use UsePrivateIP. This error is thrown when the LoadBalancer task has no Network set, so kOps cannot resolve the networkID for hcloud LoadBalancerCreateOpts.
Solutions
- Add the Hetzner network configuration to the cluster spec so the LoadBalancer task gets a Network, then re-run kops update cluster --yes.
- Ensure the cluster's network task is created before the load balancer (check the task builder wiring so e.Network is populated via dependencies).
- If a networkless LB is truly desired, the create path must be changed to omit the Network/UsePrivateIP fields — this is not supported by the current kOps Hetzner implementation, so do not bypass it.
Example fix
// before: cluster.yaml without hetzner network
spec:
networkID: "" # no network -> LoadBalancer task has Network == nil
// after: define the network in the cluster spec so the LB task resolves it
spec:
network:
networkID: "1234567"
zone: fsn1-dc14 Defensive patterns
Strategy: validation
Validate before calling
if e.Network == nil || fi.ValueOf(e.Network.ID) == "" {
return fmt.Errorf("hetzner load balancer %q requires a network; set networkID in the cluster spec", fi.ValueOf(e.Name))
}
if _, err := strconv.ParseInt(fi.ValueOf(e.Network.ID), 10, 64); err != nil {
return fmt.Errorf("network ID %q is not numeric", fi.ValueOf(e.Network.ID))
} Type guard
func hasNetwork(e *LoadBalancer) bool {
return e.Network != nil && fi.ValueOf(e.Network.ID) != ""
} Prevention
- Always configure a Hetzner network in the cluster spec before enabling load balancers
- Validate the cluster manifest (kops edit / kops validate) so missing network fields are caught pre-apply
- Keep the Network dependency wired in the task builder so the ID is populated before RenderHetzner
When it happens
Trigger: A Hetzner cluster is applied without a network defined in the cluster spec, so the LoadBalancer task's Network field is nil at render time; or the task graph omitted the Network dependency when constructing the LoadBalancer task.
Common situations: Cluster spec missing spec.networking.hetzner / network configuration; hand-edited or partial cluster manifest; version mismatch where the load balancer was introduced requiring a network the cluster never had.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- failed to find load-balancer
- failed to find load-balancer
- cannot determine challenge endpoint for server
- expected exactly one subnet with GCE IP Aliases
- failed to convert network ID
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/12c27939be181525.
Report an issue: GitHub.
Appendix: source
Thrown at upup/pkg/fi/cloudup/hetznertasks/loadbalancer.go:235
}
if len(e.Services) == 0 {
return fi.RequiredField("Services")
}
if e.Target == "" {
return fi.RequiredField("Target")
}
}
return nil
}
func (_ *LoadBalancer) RenderHetzner(t *hetzner.HetznerAPITarget, a, e, changes *LoadBalancer) error {
ctx := context.TODO()
actionClient := t.Cloud.ActionClient()
client := t.Cloud.LoadBalancerClient()
if a == nil {
if e.Network == nil {
return fmt.Errorf("failed to find network for loadbalancer %q", fi.ValueOf(e.Name))
}
networkID, err := strconv.ParseInt(fi.ValueOf(e.Network.ID), 10, 64)
if err != nil {
return fmt.Errorf("failed to convert network ID %q to int: %w", fi.ValueOf(e.Network.ID), err)
}
opts := hcloud.LoadBalancerCreateOpts{
Name: fi.ValueOf(e.Name),
LoadBalancerType: &hcloud.LoadBalancerType{
Name: e.Type,
},
Algorithm: &hcloud.LoadBalancerAlgorithm{
Type: hcloud.LoadBalancerAlgorithmTypeRoundRobin,
},
Location: &hcloud.Location{
Name: e.Location,
},View on GitHub (pinned to 4c8573c808)