tailscale/tailscale · error
storing device IPs and FQDN in Kubernetes Secret: %w
Error message
storing device IPs and FQDN in Kubernetes Secret: %w
What it means
After routing rules are successfully installed, operator-managed proxies patch the node's FQDN and tailnet IPs into 'device_fqdn'/'device_ips' of the state Secret (storeDeviceEndpoints, kube.go:76 -> StrategicMergePatchSecret). The operator reads these to publish proxy endpoints (e.g. on Ingress status) and treats them as a readiness signal, so any Kubernetes API failure here is fatal to containerboot.
Source
Thrown at cmd/containerboot/main.go:893
}
}
currentIPs = newCurrentIPs
// Only store device FQDN and IP addresses to
// Kubernetes Secret when any required proxy
// route setup has succeeded. IPs and FQDN are
// read from the Secret by the Tailscale
// Kubernetes operator and, for some proxy
// types, such as Tailscale Ingress, advertized
// on the Ingress status. Writing them to the
// Secret only after the proxy routing has been
// set up ensures that the operator does not
// advertize endpoints of broken proxies.
// TODO (irbekrm): instead of using the IP and FQDN, have some other mechanism for the proxy signal that it is 'Ready'.
deviceEndpoints := []any{self.Name(), self.Addresses()}
if hasKubeStateStore(cfg) && deephash.Update(¤tDeviceEndpoints, &deviceEndpoints) {
if err := kc.storeDeviceEndpoints(ctx, self.Name(), addrs); err != nil {
return fmt.Errorf("storing device IPs and FQDN in Kubernetes Secret: %w", err)
}
}
if healthCheck != nil {
healthCheck.Update(len(addrs) != 0)
}
var prevServeConfig *ipn.ServeConfig
if getAutoAdvertiseBool() {
prevServeConfig, err = client.GetServeConfig(ctx)
if err != nil {
return fmt.Errorf("autoadvertisement: failed to get serve config: %w", err)
}
err = refreshAdvertiseServices(ctx, prevServeConfig, klc.New(client))
if err != nil {
return fmt.Errorf("autoadvertisement: failed to refresh advertise services: %w", err)
}View on GitHub (pinned to cfe32b8be6)
Solutions
- Verify the Secret exists: kubectl get secret <name>
- Verify RBAC: kubectl auth can-i patch secret <name> as the pod's ServiceAccount
- Check apiserver connectivity and any admission webhook rejecting the patch
- Recreate the proxy resource so the operator rebuilds state
Defensive patterns
Strategy: validation
Validate before calling
# readiness of the state store before endpoints are published kubectl get secret "$STATE_SECRET" -o name >/dev/null || echo "state Secret missing" kubectl auth can-i patch secret "$STATE_SECRET" >/dev/null || echo "no patch permission"
Prevention
- Do not delete or rename state Secrets under running proxies
- Gate external automation (GitOps prunes) on operator-owned resources
- Monitor proxy Secrets for unexpected mutations
When it happens
Trigger: State Secret deleted or renamed; ServiceAccount lacking get/patch on secrets; kube-apiserver unreachable; patch rejected with 409/422; expired SA tokens.
Common situations: Manual deletion of the state Secret while proxies run; missing Role bindings in custom operator installs; API server outages; strict namespace quotas or validating webhooks rejecting the patch.
Related errors
- storing device ID in Kubernetes Secret: %w
- error retrieving current egress proxy status: %w
- error setting egress proxy status: %w
- error retrieving state Secret: %w
- error patching state Secret: %w
AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15).
Data as JSON: /api/errors/2afd802ca601e1a4.
Report an issue: GitHub.