tailscale/tailscale · warning
error deleting Role for domain name %s: %w
Error message
error deleting Role for domain name %s: %w
What it means
During cert cleanup, cl.DeleteAllOf for Roles labelled with the ProxyGroup name and domain failed — the Role half of the cert RBAC pair. Identical failure modes to the RoleBinding deletion: RBAC denial or apiserver error. Cleanup stops before the Secret deletion step, so resources leak until a successful retry.
Source
Thrown at cmd/k8s-operator/ingress-for-pg.go:1009
}); err != nil {
return fmt.Errorf("failed to create or update RoleBinding %s: %w", rolebinding.Name, err)
}
return nil
}
// cleanupCertResources ensures that the TLS Secret and associated RBAC
// resources that allow proxies to read/write to the Secret are deleted.
func cleanupCertResources(ctx context.Context, cl client.Client, tsNamespace string, serviceName tailcfg.ServiceName, pg *tsapi.ProxyGroup) error {
domainName, err := dnsNameForService(ctx, cl, serviceName, pg, tsNamespace)
if err != nil {
return fmt.Errorf("error getting DNS name for Tailscale Service %s: %w", serviceName, err)
}
labels := certResourceLabels(pg.Name, domainName)
if err := cl.DeleteAllOf(ctx, &rbacv1.RoleBinding{}, client.InNamespace(tsNamespace), client.MatchingLabels(labels)); err != nil {
return fmt.Errorf("error deleting RoleBinding for domain name %s: %w", domainName, err)
}
if err := cl.DeleteAllOf(ctx, &rbacv1.Role{}, client.InNamespace(tsNamespace), client.MatchingLabels(labels)); err != nil {
return fmt.Errorf("error deleting Role for domain name %s: %w", domainName, err)
}
if err := cl.DeleteAllOf(ctx, &corev1.Secret{}, client.InNamespace(tsNamespace), client.MatchingLabels(labels)); err != nil {
return fmt.Errorf("error deleting Secret for domain name %s: %w", domainName, err)
}
return nil
}
// requeueInterval returns a time duration between 5 and 10 minutes, which is
// the period of time after which an HA Ingress, whose Tailscale Service has been newly
// created or changed, needs to be requeued. This is to protect against
// Tailscale Service's owner references being overwritten as a result of concurrent
// updates during multi-clutster Ingress create/update operations.
func requeueInterval() time.Duration {
return time.Duration(rand.N(5)+5) * time.Minute
}
// certSecretRole creates a Role that will allow proxies to manage the TLS
// Secret for the given domain. Domain must be a valid Kubernetes resource name.View on GitHub (pinned to cfe32b8be6)
Solutions
- Verify operator can delete roles in its namespace
- Let the reconciler retry — DeleteAllOf is idempotent
- Manually delete leftovers: kubectl delete role -n <operator-ns> -l tailscale.com/parent-proxy-group=<pgName>
Defensive patterns
Strategy: retry
Try / catch
if err := cl.DeleteAllOf(ctx, &rbacv1.Role{}, client.InNamespace(ns), client.MatchingLabels(labels)); err != nil {
if apierrors.IsNotFound(err) {
return nil
}
return fmt.Errorf("error deleting Role for domain name %s: %w", domainName, err)
} Prevention
- Keep roles.rbac.authorization.k8s.io delete in the operator ClusterRole
- Check admission controllers when collection deletes fail consistently
- Reconcile leftover labelled Roles during operator upgrades
When it happens
Trigger: cl.DeleteAllOf(ctx, &rbacv1.Role{}, client.InNamespace(tsNamespace), client.MatchingLabels(labels)) after the RoleBinding delete in cleanupCertResources. Fires on missing delete on roles or control-plane errors.
Common situations: Narrowed ClusterRole without role delete; admission webhooks blocking collection deletes; overloaded apiserver during cluster teardown.
Related errors
- error deleting RoleBinding for domain name %s: %w
- storing device ID in Kubernetes Secret: %w
- storing device IPs and FQDN in Kubernetes Secret: %w
- failed to create or update Role %s: %w
- failed to create or update RoleBinding %s: %w
AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15).
Data as JSON: /api/errors/6c034d96c2b3cf78.
Report an issue: GitHub.