{"record":{"id":"b4b83a9d727610da","repo":"kubernetes/kops","slug":"failed-to-get-info-for-load-balancer-q-w","errorCode":null,"errorMessage":"failed to get info for load balancer %q: %w","messagePattern":"failed to get info for load balancer %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/hetzner/cloud.go","lineNumber":441,"sourceCode":"\n// FindVPCInfo is not implemented\nfunc (c *hetznerCloudImplementation) FindVPCInfo(id string) (*fi.VPCInfo, error) {\n\t// TODO(hakman): Implement me\n\treturn nil, errors.New(\"hetzner cloud provider does not implement FindVPCInfo at this time\")\n}\n\n// FindClusterStatus was used before etcd-manager to check the etcd cluster status and prevent unsupported changes.\nfunc (c *hetznerCloudImplementation) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error) {\n\treturn nil, nil\n}\n\nfunc (c *hetznerCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {\n\tlbName := \"api.\" + cluster.Name\n\n\tclient := c.LoadBalancerClient()\n\tlb, _, err := client.GetByName(context.TODO(), lbName)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get info for load balancer %q: %w\", lbName, err)\n\t}\n\tif lb == nil {\n\t\treturn nil, nil\n\t}\n\n\tif !lb.PublicNet.Enabled {\n\t\treturn nil, fmt.Errorf(\"load balancer %s(%d) is not public\", lb.Name, lb.ID)\n\t}\n\n\tingresses := []fi.ApiIngressStatus{\n\t\t{\n\t\t\tIP: lb.PublicNet.IPv4.IP.String(),\n\t\t},\n\t}\n\n\treturn ingresses, nil\n}\n","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/hetzner/cloud.go#L423-L459","documentation":"GetApiIngressStatus looks up the cluster's API load balancer by name (\"api.<cluster>\") via LoadBalancerClient.GetByName. If that Hetzner API call errors (network, auth, API failure), the error is wrapped with the LB name. This is not the same as the LB not existing — a nil lb with nil error returns gracefully.","triggerScenarios":"The hcloud LoadBalancer GetByName request fails: invalid HCLOUD_TOKEN, network timeout, rate limit, or Hetzner API 5xx.","commonSituations":"Expired/incorrect API token during `kops rolling-update` or `kops validate`; Hetzner API outage; corporate proxy blocking api.hetzner.cloud.","solutions":["Check the wrapped error: 401 => fix HCLOUD_TOKEN, timeout => check network/proxy.","Verify token with `curl -H \"Authorization: Bearer $HCLOUD_TOKEN\" https://api.hetzner.cloud/v1/load_balancers`.","Retry after transient failures.","If the LB was intentionally deleted, recreate it via `kops update cluster`."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"resp, _ := http.Get(\"https://api.hetzner.cloud/v1\") // plus token auth check before running\nif resp.StatusCode == 401 { /* fix token first */ }","typeGuard":null,"tryCatchPattern":"lb, _, err := client.GetByName(ctx, lbName)\nif err != nil {\n  var hErr *hcloud.ErrorResponse\n  if errors.As(err, &hErr) && hErr.Code == \"rate_limit_exceeded\" {\n    // back off and retry\n  }\n  return nil, fmt.Errorf(\"failed to get info for load balancer %q: %w\", lbName, err)\n}","preventionTips":["Verify HCLOUD_TOKEN validity before API-heavy operations.","Distinguish \"not found\" (nil lb, nil err) from transport errors.","Retry transient Hetzner API failures with exponential backoff."],"tags":["hetzner","load-balancer","api"],"backgroundTag":"cloud-api-request-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}