{"record":{"id":"d4c2b9f2bed5b341","repo":"argoproj/argo-workflows","slug":"failed-to-get-service-account-secret-w","errorCode":null,"errorMessage":"failed to get service account secret: %w","messagePattern":"failed to get service account secret: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/auth/gatekeeper.go","lineNumber":326,"sourceCode":"\tfields := logging.Fields{\n\t\t\"serviceAccount\":       delegatedAccount.Name,\n\t\t\"subject\":              claims.Subject,\n\t\t\"email\":                claims.Email,\n\t\t\"ssoDelegationAllowed\": ssoDelegationAllowed,\n\t\t\"ssoDelegated\":         ssoDelegated,\n\t}\n\tif loginAccount != nil {\n\t\tfields[\"loginServiceAccount\"] = loginAccount.Name\n\t}\n\tlogger.WithFields(fields).Info(ctx, \"selected SSO RBAC service account for user\")\n\treturn s.getClientsForServiceAccount(ctx, claims, delegatedAccount)\n}\n\nfunc (s *gatekeeper) authorizationForServiceAccount(ctx context.Context, serviceAccount *corev1.ServiceAccount) (string, error) {\n\tsecretName := secrets.TokenNameForServiceAccount(serviceAccount)\n\tsecret, err := s.cache.GetSecret(ctx, serviceAccount.GetNamespace(), secretName)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get service account secret: %w\", err)\n\t}\n\treturn \"Bearer \" + string(secret.Data[\"token\"]), nil\n}\n\nfunc addClaimsLogFields(claims *authTypes.Claims, fields logging.Fields) logging.Fields {\n\tif fields == nil {\n\t\tfields = logging.Fields{}\n\t}\n\tfields[\"subject\"] = claims.Subject\n\tif claims.Email != \"\" {\n\t\tfields[\"email\"] = claims.Email\n\t}\n\treturn fields\n}\n\nfunc DefaultClientForAuthorization(authorization string, config *rest.Config) (*rest.Config, *servertypes.Clients, error) {\n\trestConfig, err := kubeconfig.GetRestConfig(authorization)\n\tif err != nil {","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/auth/gatekeeper.go#L308-L344","documentation":"After a rule-matched service account is chosen, the server builds a per-user k8s client by reading the SA's token Secret (secrets.TokenNameForServiceAccount). This error wraps a failure fetching that secret from the informer cache — typically the secret doesn't exist or isn't readable, so the server cannot impersonate the matched service account. On Kubernetes 1.24+ long-lived SA token secrets are no longer auto-created, so this frequently fires when relying on legacy auto-generated token secrets.","triggerScenarios":"SSO RBAC matched a ServiceAccount, but GetSecret(ns, <sa-name>-token-xxx) fails: the token secret was deleted, never created (K8s >= 1.24 no auto token secrets), or was created without the kubernetes.io/service-account-token type / correct sa annotation.","commonSituations":"Upgrading to Kubernetes 1.24+ where SA token secrets are no longer auto-generated; manually created SAs in clusters where the controller manager's token cleaner removed the secret; creating a secret with the wrong `type` or missing `kubernetes.io/service-account.name` annotation; RBAC preventing argo-server's service account from reading secrets in the target namespace.","solutions":["Create a long-lived token secret properly and reference it: a secret of type kubernetes.io/service-account-token with annotation kubernetes.io/service-account.name: <sa>; k8s will fill the token field.","On K8s >=1.24, prefer creating the secret explicitly (legacy auto-generation is gone) and restart/re-sync so the informer cache sees it.","Verify the secret exists: `kubectl -n <ns> get secret` for the name TokenNameForServiceAccount derives (`<sa-name>-token-...` or the secret named via the SA's secrets list), and that its `token` key is populated.","Check argo-server's RBAC allows reading secrets in the SSO/delegated namespaces, and that the SA has the secret listed under `secrets:`."],"exampleFix":"# before: SA with no token secret (k8s 1.24+)\nkind: ServiceAccount\nmetadata:\n  name: argo-sso\n# after: explicit long-lived token secret\nkind: ServiceAccount\nmetadata:\n  name: argo-sso\nsecrets:\n  - name: argo-sso-token\n---\napiVersion: v1\nkind: Secret\nmetadata:\n  name: argo-sso-token\n  annotations:\n    kubernetes.io/service-account.name: argo-sso\ntype: kubernetes.io/service-account-token","handlingStrategy":"retry","validationCode":"SA=<name>; NS=<ns>\nkubectl -n $NS get secret \"${SA}-token\" -o jsonpath='{.type} {.data.token}'  # expect kubernetes.io/service-account-token and a non-empty token","typeGuard":null,"tryCatchPattern":"// server retries via informer cache; client sees PermissionDenied/Unauthenticated\nif st, ok := status.FromError(err); ok && st.Code() == codes.PermissionDenied {\n    time.Sleep(2 * time.Second) // allow secret propagation into informer cache, then retry once\n}","preventionTips":["On K8s >=1.24 always create explicit token secrets for SSO RBAC SAs","Secret must be type kubernetes.io/service-account-token with the service-account.name annotation","Grant argo-server RBAC to get secrets in SSO and delegated namespaces","Recreate the secret if the token-controller purged it; avoid tools that strip SA token secrets"],"tags":["kubernetes","service-account","secrets","sso","rbac"],"backgroundTag":"service-account-token-secret-missing","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}