{"record":{"id":"3076b6c56acc50d6","repo":"kubernetes/kops","slug":"error-getting-host-v-w","errorCode":null,"errorMessage":"error getting host %v: %w","messagePattern":"error getting host (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/bootstrap/pkibootstrap/pkiverifier/verifier.go","lineNumber":143,"sourceCode":"\tif !verifySignature(signingKey, token.Data, token.Signature) {\n\t\treturn nil, fmt.Errorf(\"failed to verify claim signature for node\")\n\t}\n\n\treturn result, nil\n}\n\nfunc (v *verifier) getSigningKey(ctx context.Context, tokenData *pkibootstrap.AuthTokenData) (*bootstrap.VerifyResult, crypto.PublicKey, error) {\n\tnodeName := tokenData.Instance\n\tid := types.NamespacedName{\n\t\tNamespace: \"kops-system\",\n\t\tName:      nodeName,\n\t}\n\tvar host kops.Host\n\tif err := v.client.Get(ctx, id, &host); err != nil {\n\t\tif apierrors.IsNotFound(err) {\n\t\t\treturn nil, nil, fmt.Errorf(\"host not found for %v\", id)\n\t\t}\n\t\treturn nil, nil, fmt.Errorf(\"error getting host %v: %w\", id, err)\n\t}\n\n\t// TODO: Check instance-group matches request (does it matter?)\n\n\tif host.Spec.PublicKey == \"\" {\n\t\treturn nil, nil, fmt.Errorf(\"host %v did not have public-key\", id)\n\t}\n\tinstanceGroup := host.Spec.InstanceGroup\n\tif instanceGroup == \"\" {\n\t\treturn nil, nil, fmt.Errorf(\"host %v did not have spec.instanceGroup\", id)\n\t}\n\tpubKey, err := pki.ParsePEMPublicKey([]byte(host.Spec.PublicKey))\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to parse public key: %w\", err)\n\t}\n\n\tvar sans []string\n","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/bootstrap/pkibootstrap/pkiverifier/verifier.go#L125-L161","documentation":"This wraps any error from the controller-runtime client Get that is NOT a NotFound, when fetching the kops.Host for a bootstrapping node. It signals an infrastructure/API problem (API server unreachable, RBAC denial, timeout, CRD missing) rather than a missing Host record, and the underlying error is chained via %w.","triggerScenarios":"VerifyToken -> getSigningKey issues a client.Get for a Host in kops-system and the API server returns a non-NotFound error: connection refused/timeout, 403 Forbidden from RBAC on kops.k8s.io/hosts, Host CRD not installed (no matches for kind), or too many requests/throttling.","commonSituations":"kops-controller ServiceAccount lacks RBAC rules for the Host resource; Host CRD not yet applied after an upgrade; API server overloaded or etcd degraded; network policy or egress issue between kops-controller and apiserver; custom resource renamed across kops versions.","solutions":["Read the wrapped cause (errors.Unwrap or kops-controller logs) to identify whether it is RBAC, connection, or CRD related","Ensure the Host CRD (kops.k8s.io) is installed: kubectl get crd hosts.kops.k8s.io","Grant kops-controller's ServiceAccount RBAC get/list on hosts.kops.k8s.io in the kops-system namespace","Verify kops-controller can reach the API server (network policies, DNS, etcd health)"],"exampleFix":"// before: RBAC missing, Get returns Forbidden\n// kubectl auth can-i get hosts.kops.k8s.io -n kops-system --as=system:serviceaccount:kops-system:kops-controller -> no\n\n// after: add ClusterRole rule\n// rules:\n// - apiGroups: [\"kops.k8s.io\"]\n//   resources: [\"hosts\"]\n//   verbs: [\"get\", \"list\", \"watch\"]","handlingStrategy":"try-catch","validationCode":"var probe kops.Host\nif err := c.Get(ctx, types.NamespacedName{Namespace: \"kops-system\", Name: probeName}, &probe); err != nil {\n    if !apierrors.IsNotFound(err) {\n        return fmt.Errorf(\"API access to Hosts is broken: %w\", err)\n    }\n}","typeGuard":"func isAPIAccessError(err error) bool {\n    return err != nil && !apierrors.IsNotFound(err) && strings.Contains(err.Error(), \"error getting host\")\n}","tryCatchPattern":"result, err := verifier.VerifyToken(ctx, req, token, body)\nif err != nil {\n    var se *apierrors.StatusError\n    if errors.As(err, &se) {\n        switch apierrors.ReasonForError(se) {\n        case metav1.ReasonForbidden:\n            return fmt.Errorf(\"fix kops-controller RBAC for hosts.kops.k8s.io: %w\", err)\n        }\n    }\n    return err\n}","preventionTips":["Verify kubectl auth can-i get hosts.kops.k8s.io -n kops-system for the controller ServiceAccount","Install/upgrade the Host CRD alongside kops-controller","Alert on API server availability and kops-controller error rates","Re-run RBAC generation after kops version upgrades"],"tags":["kubernetes","rbac","api-server","client-error"],"backgroundTag":"api-request-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}