{"record":{"id":"51d0227e84c90b7e","repo":"tailscale/tailscale","slug":"failed-to-check-if-any-pods-are-configured-w","errorCode":null,"errorMessage":"failed to check if any Pods are configured: %w","messagePattern":"failed to check if any Pods are configured: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/k8s-operator/ingress-for-pg.go","lineNumber":380,"sourceCode":"\t\tif err := tsClient.VIPServices().CreateOrUpdate(ctx, tsSvc); err != nil {\n\t\t\treturn false, fmt.Errorf(\"error creating Tailscale Service: %w\", err)\n\t\t}\n\t}\n\n\t// 5. Update tailscaled's AdvertiseServices config, which should add the Tailscale Service\n\t// IPs to the ProxyGroup Pods' AllowedIPs in the next netmap update if approved.\n\tmode := serviceAdvertisementHTTPS\n\tif isHTTPEndpointEnabled(ing) || isHTTPRedirectEnabled(ing) {\n\t\tmode = serviceAdvertisementHTTPAndHTTPS\n\t}\n\tif err = r.maybeUpdateAdvertiseServicesConfig(ctx, serviceName, mode, pg); err != nil {\n\t\treturn false, fmt.Errorf(\"failed to update tailscaled config: %w\", err)\n\t}\n\n\t// 6. Update Ingress status if ProxyGroup Pods are ready.\n\tcount, err := numberPodsAdvertising(ctx, r.Client, r.tsNamespace, pg.Name, serviceName.String())\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"failed to check if any Pods are configured: %w\", err)\n\t}\n\n\toldStatus := ing.Status.DeepCopy()\n\n\tswitch count {\n\tcase 0:\n\t\ting.Status.LoadBalancer.Ingress = nil\n\tdefault:\n\t\tvar ports []networkingv1.IngressPortStatus\n\t\thasCerts, err := hasCerts(ctx, r.Client, r.tsNamespace, serviceName, pg)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"error checking TLS credentials provisioned for Ingress: %w\", err)\n\t\t}\n\t\t// If TLS certs have not been issued (yet), do not set port 443.\n\t\tif hasCerts {\n\t\t\tports = append(ports, networkingv1.IngressPortStatus{\n\t\t\t\tProtocol: \"TCP\",\n\t\t\t\tPort:     443,","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/cmd/k8s-operator/ingress-for-pg.go#L362-L398","documentation":"Thrown by HAIngressReconciler.maybeProvision when numberPodsAdvertising fails: it lists the ProxyGroup's state Secrets (label-selected on ProxyGroup name and secret type state) and parses device prefs from each. The wrapped error is either the Secret list call failing (RBAC/apiserver) or getDevicePrefs choking on a state Secret whose prefs bytes do not unmarshal ('error getting node metadata'). The count is used to decide whether Ingress status may advertise the service.","triggerScenarios":"List of state Secrets in the operator namespace denied or failing; a state Secret written partially, hand-edited, or left by a different operator version so prefs do not unmarshal; ctx cancelled while listing.","commonSituations":"ProxyGroup replica scaled up/down leaving stale Secrets; state Secret corrupted after a pod crash mid-write; restrictive admission/OPA blocking list; apiserver throttling.","solutions":["Read the wrapped error: 'error getting node metadata' means a corrupt state Secret; inspect the ProxyGroup's state Secrets (kubectl get secrets -n <operator-ns> -l tailscale.com/parent=<pg>) and delete the corrupt/orphaned one so the pod regenerates it.","'forbidden'/apiserver errors: reapply RBAC or wait out the transient; the reconcile backoff retries.","Ensure ProxyGroup Pods are healthy so they rewrite valid state Secrets."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"func isCorruptStateSecretErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"node metadata\")\n}","tryCatchPattern":"count, err := numberPodsAdvertising(ctx, r.Client, r.tsNamespace, pg.Name, serviceName.String())\nif err != nil {\n\tif isCorruptStateSecretErr(err) {\n\t\tlogger.Error(\"corrupt ProxyGroup state Secret; regenerate it before retrying\")\n\t}\n\treturn ctrl.Result{}, fmt.Errorf(\"failed to check if any Pods are configured: %w\", err)\n}","preventionTips":["Let the operator own ProxyGroup state Secrets end to end.","When scaling ProxyGroup replicas, rely on the operator to retire old Secrets.","Monitor ProxyGroup Pod health; unhealthy pods leave stale state."],"tags":["kubernetes","secrets","proxygroup","readiness","json"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}