{"record":{"id":"08907b01313a5fec","repo":"kubernetes/kops","slug":"did-not-find-api-endpoint","errorCode":null,"errorMessage":"did not find API endpoint","messagePattern":"did not find API endpoint","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/controllers/clusterapi/cluster_controller.go","lineNumber":228,"sourceCode":"\t\t\ttarget.Endpoint = ingress.Hostname\n\t\t}\n\t\tif ingress.IP != \"\" {\n\t\t\ttarget.Endpoint = ingress.IP\n\t\t}\n\t\ttarget.Type = capikops.SystemEndpointTypeKubeAPIServer\n\t\tif ingress.InternalEndpoint {\n\t\t\ttarget.Scope = capikops.SystemEndpointScopeInternal\n\t\t} else {\n\t\t\ttarget.Scope = capikops.SystemEndpointScopeExternal\n\t\t}\n\t\ttargets = append(targets, target)\n\t}\n\n\t// TODO: Sort targets\n\t// TODO: Mark targets as atomic list\n\n\tif len(targets) == 0 {\n\t\treturn nil, fmt.Errorf(\"did not find API endpoint\")\n\t}\n\n\treturn targets, nil\n}\n\nfunc (s *clusterScope) createKopsControlPlane(ctx context.Context, kube client.Client) error {\n\t// This is because of network tags in cloud-provider-gcp\n\t// TODO: cloud-provider-gcp should not assume cluster name is a valid prefix\n\tname := gce.SafeClusterName(s.Cluster.GetName())\n\n\tstatus := capikops.KopsControlPlaneStatus{}\n\n\tsystemEndpoints, err := s.findSystemEndpoints(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tstatus.SystemEndpoints = systemEndpoints\n","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/controllers/clusterapi/cluster_controller.go#L210-L246","documentation":"After querying GetApiIngressStatus, findSystemEndpoints builds a list of SystemEndpoint values (kops-controller and kube-apiserver addresses). If the cloud returns an empty ingress list — no hostnames and no IPs — there is nothing to publish and the controller raises 'did not find API endpoint'. This prevents creating a KopsControlPlane whose status has no usable endpoints, which would later break bootstrap-data generation.","triggerScenarios":"The API load balancer has no ingress entries yet (LB created but no addresses assigned), the load balancer was deleted, or the cloud provider returns an empty list for a cluster whose networking is not yet wired (e.g. missing subnets/frontend IP).","commonSituations":"Reconcile fires immediately after cluster creation before the LB gets an external IP/hostname; private-only clusters where only internal endpoints exist and the provider omits them; LB misconfiguration in the cloud console.","solutions":["Wait for the API load balancer to be assigned an IP/hostname and re-reconcile (controller will retry)","Verify the load balancer frontend and target pools/backends are configured in the cloud console","Check the cluster spec networking (subnets, networkID) matches the actual cloud resources","If using internal-only endpoints, confirm the provider surfaces internal ingress entries"],"exampleFix":"// before\nif len(targets) == 0 {\n    return nil, fmt.Errorf(\"did not find API endpoint\")\n}\n// after: requeue instead of erroring while the LB is still provisioning\nif len(targets) == 0 {\n    return ctrl.Result{RequeueAfter: 30 * time.Second}, nil\n}","handlingStrategy":"retry","validationCode":"ingresses, _ := cloud.GetApiIngressStatus(clusterInternal)\nif len(ingresses) == 0 {\n    klog.Warning(\"API load balancer has no ingress addresses yet\")\n}","typeGuard":null,"tryCatchPattern":"endpoints, err := s.findSystemEndpoints(ctx)\nif err != nil && err.Error() == \"did not find API endpoint\" {\n    return ctrl.Result{RequeueAfter: 30 * time.Second}, nil // LB still provisioning\n}","preventionTips":["Check the load balancer has an assigned IP/hostname in the cloud console","Confirm subnets/network config in the cluster spec match reality","Allow time between cluster creation and first reconcile","For private clusters, verify internal ingress entries are surfaced by the provider"],"tags":["load-balancer","endpoints","controller","cloud"],"backgroundTag":"api-endpoint-not-found","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"}