{"record":{"id":"3ab384ec0ad5c6fe","repo":"tailscale/tailscale","slug":"failed-to-get-endpointslice-w","errorCode":null,"errorMessage":"failed to get EndpointSlice: %w","messagePattern":"failed to get EndpointSlice: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/k8s-operator/egress-eps.go","lineNumber":50,"sourceCode":"}\n\n// Reconcile reconciles an EndpointSlice for a tailnet service. It updates the EndpointSlice with the endpoints of\n// those ProxyGroup Pods that are ready to route traffic to the tailnet service.\n// It compares tailnet service state stored in egress proxy state Secrets by containerboot with the desired\n// configuration stored in proxy-cfg ConfigMap to determine if the endpoint is ready.\nfunc (er *egressEpsReconciler) Reconcile(ctx context.Context, req reconcile.Request) (res reconcile.Result, err error) {\n\tlg := er.logger.With(\"Service\", req.NamespacedName)\n\tlg.Debugf(\"starting reconcile\")\n\tdefer lg.Debugf(\"reconcile finished\")\n\n\teps := new(discoveryv1.EndpointSlice)\n\terr = er.Get(ctx, req.NamespacedName, eps)\n\tif apierrors.IsNotFound(err) {\n\t\tlg.Debugf(\"EndpointSlice not found\")\n\t\treturn reconcile.Result{}, nil\n\t}\n\tif err != nil {\n\t\treturn reconcile.Result{}, fmt.Errorf(\"failed to get EndpointSlice: %w\", err)\n\t}\n\tif !eps.DeletionTimestamp.IsZero() {\n\t\tlg.Debugf(\"EnpointSlice is being deleted\")\n\t\treturn res, nil\n\t}\n\n\t// Get the user-created ExternalName Service and use its status conditions to determine whether cluster\n\t// resources are set up for this tailnet service.\n\tsvc := &corev1.Service{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      eps.Labels[LabelParentName],\n\t\t\tNamespace: eps.Labels[LabelParentNamespace],\n\t\t},\n\t}\n\terr = er.Get(ctx, client.ObjectKeyFromObject(svc), svc)\n\tif apierrors.IsNotFound(err) {\n\t\tlg.Infof(\"ExternalName Service %s/%s not found, perhaps it was deleted\", svc.Namespace, svc.Name)\n\t\treturn res, nil","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/cmd/k8s-operator/egress-eps.go#L32-L68","documentation":"Thrown by the egress EndpointSlice reconciler when controller-runtime's Get of the EndpointSlice fails with an error other than NotFound (NotFound is handled one line above and returns cleanly). Any error reaching this line is infrastructure-level: API server connectivity problems, RBAC denying discovery.k8s.io EndpointSlices get, throttling, or a canceled context.","triggerScenarios":"The operator's service account lacks get on endpointslices (RBAC regression); API server temporarily unreachable or overloaded (429/503); watch/cache resync races surfacing as transient read failures; request context canceled during reconciliation.","commonSituations":"Deploying a new operator version without the updated ClusterRole; apiserver disruption causing reconcile storms; large clusters where list/watch pressure produces throttled reads.","solutions":["Verify the operator ClusterRole includes verbs=[get,list,watch] on discovery.k8s.io/endpointslices","Check apiserver health and client-side rate limiting (client-side QPS/burst settings)","Do nothing special for single occurrences — returning the error makes controller-runtime requeue with exponential backoff","If persistent, inspect operator logs for the wrapped error text and fix that root cause"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// Distinguish handled not-found from real infrastructure errors\nfunc isInfraErr(err error) bool {\n\treturn err != nil && !apierrors.IsNotFound(err)\n}","tryCatchPattern":"// Go: return the error; controller-runtime requeues with exponential backoff\nerr = er.Get(ctx, req.NamespacedName, eps)\nif apierrors.IsNotFound(err) {\n\treturn reconcile.Result{}, nil\n}\nif err != nil {\n\treturn reconcile.Result{}, fmt.Errorf(\"failed to get EndpointSlice: %w\", err)\n}","preventionTips":["Keep the ClusterRole for the operator in sync with every new watched type","Never swallow non-NotFound Get errors — returning them is what powers backoff requeue","Alert on elevated reconcile error rates rather than individual transient failures"],"tags":["kubernetes","controller-runtime","rbac","reconcile"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}