{"record":{"id":"00c69f3148ec08b5","repo":"tailscale/tailscale","slug":"failed-to-get-ing-w","errorCode":null,"errorMessage":"failed to get ing: %w","messagePattern":"failed to get ing: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/k8s-operator/ingress.go","lineNumber":76,"sourceCode":"var (\n\t// gaugeIngressResources tracks the number of ingress resources that we're\n\t// currently managing.\n\tgaugeIngressResources = clientmetric.NewGauge(kubetypes.MetricIngressResourceCount)\n)\n\nfunc (a *IngressReconciler) Reconcile(ctx context.Context, req reconcile.Request) (_ reconcile.Result, err error) {\n\tlogger := a.logger.With(\"Ingress\", req.NamespacedName)\n\tlogger.Debugf(\"starting reconcile\")\n\tdefer logger.Debugf(\"reconcile finished\")\n\n\ting := new(networkingv1.Ingress)\n\terr = a.Get(ctx, req.NamespacedName, ing)\n\tif apierrors.IsNotFound(err) {\n\t\t// Request object not found, could have been deleted after reconcile request.\n\t\tlogger.Debugf(\"ingress not found, assuming it was deleted\")\n\t\treturn reconcile.Result{}, nil\n\t} else if err != nil {\n\t\treturn reconcile.Result{}, fmt.Errorf(\"failed to get ing: %w\", err)\n\t}\n\tif !ing.DeletionTimestamp.IsZero() || !a.shouldExpose(ing) {\n\t\t// TODO(irbekrm): this message is confusing if the Ingress is an HA Ingress\n\t\tlogger.Debugf(\"ingress is being deleted or should not be exposed, cleaning up\")\n\t\treturn reconcile.Result{}, a.maybeCleanup(ctx, logger, ing)\n\t}\n\n\tif err := a.maybeProvision(ctx, logger, ing); err != nil {\n\t\tif strings.Contains(err.Error(), optimisticLockErrorMsg) {\n\t\t\tlogger.Infof(\"optimistic lock error, retrying: %s\", err)\n\t\t} else {\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\t}\n\n\treturn reconcile.Result{}, nil\n}\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/cmd/k8s-operator/ingress.go#L58-L94","documentation":"The Ingress reconciler's initial Get of the Ingress object failed with an error other than NotFound (which is handled and treated as deletion). This is a straight Kubernetes API read failure — RBAC denial on ingresses, apiserver unreachability, or request timeout — and aborts the reconcile before any provisioning logic runs.","triggerScenarios":"a.Get(ctx, req.NamespacedName, ing) at the top of IngressReconciler.Reconcile. Fires when the operator service account cannot get ingresses in the watched namespace or the control plane call fails transiently.","commonSituations":"Operator installed without Ingress read permissions; watching a namespace it has no access to; apiserver restart; stale watch causing a re-list that errors.","solutions":["Check operator RBAC: kubectl auth can-i get ingresses --as=system:serviceaccount:<ns>:tailscale-operator","For transient errors, rely on controller-runtime's exponential backoff requeue","Verify apiserver health and operator-to-control-plane networking","Ensure the operator's ingress class filter matches a class it can watch"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"err = a.Get(ctx, req.NamespacedName, ing)\nif apierrors.IsNotFound(err) {\n    return reconcile.Result{}, nil // deleted, nothing to do\n} else if err != nil {\n    return reconcile.Result{}, fmt.Errorf(\"failed to get ing: %w\", err) // controller-runtime requeues\n}","preventionTips":["Install the operator with full bundled RBAC (ingresses get/list/watch)","Only watch namespaces the operator is granted access to","Monitor controller workqueue error rate to catch API read failures early"],"tags":["kubernetes","ingress","rbac","operator","reconcile"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}