{"record":{"id":"8b5150e9bf37077a","repo":"argoproj/argo-workflows","slug":"failed-to-get-token-secret-s-w","errorCode":null,"errorMessage":"failed to get token secret \"%s\": %w","messagePattern":"failed to get token secret \"(.+?)\": %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/auth/webhook/interceptor.go","lineNumber":107,"sourceCode":"\tserviceAccountInterface := kube.CoreV1().ServiceAccounts(namespace)\n\tfor serviceAccountName, data := range webhookClients.Data {\n\t\tr.Body = io.NopCloser(bytes.NewBuffer(buf))\n\t\tclient := &webhookClient{}\n\t\terr := yaml.Unmarshal(data, client)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to unmarshal webhook client \\\"%s\\\": %w\", serviceAccountName, err)\n\t\t}\n\t\ti.logger.WithFields(logging.Fields{\"serviceAccountName\": serviceAccountName, \"webhookType\": client.Type}).Debug(r.Context(), \"Attempting to match webhook request\")\n\t\tok := webhookParsers[client.Type](client.Secret, r)\n\t\tif ok {\n\t\t\ti.logger.WithField(\"serviceAccountName\", serviceAccountName).Debug(r.Context(), \"Matched webhook request\")\n\t\t\tserviceAccount, err := serviceAccountInterface.Get(ctx, serviceAccountName, metav1.GetOptions{})\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to get service account \\\"%s\\\": %w\", serviceAccountName, err)\n\t\t\t}\n\t\t\ttokenSecret, err := secretsInterface.Get(ctx, secrets.TokenNameForServiceAccount(serviceAccount), metav1.GetOptions{})\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to get token secret \\\"%s\\\": %w\", tokenSecret, err)\n\t\t\t}\n\t\t\tr.Header[\"Authorization\"] = []string{\"Bearer \" + string(tokenSecret.Data[\"token\"])}\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":89,"sourceCodeEnd":115,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/auth/webhook/interceptor.go#L89-L115","documentation":"After resolving the ServiceAccount, the interceptor fetches its token Secret (name derived via TokenNameForServiceAccount, typically `<sa-name>-token`). This error wraps the Kubernetes Get failure, so the webhook cannot be authorized with the SA's bearer token. Note the format argument passed is the secret variable's value at that point, which is the secret name string.","triggerScenarios":"The matched ServiceAccount exists but its token Secret was deleted (common after Kubernetes 1.24+, where tokens are no longer auto-created as Secrets and are projected instead), or RBAC blocks reading secrets, or the secret lives in a different namespace.","commonSituations":"Cluster upgraded from k8s <=1.23 to >=1.24: legacy `<sa>-token` secrets no longer auto-created; TokenController disabled; argo-server RBAC missing `get secrets`; secret manually cleaned up by a secret-sweeper job.","solutions":["Check the secret exists: `kubectl get secret <sa-name>-token -n <namespace>`; if missing and on k8s >=1.24, create a long-lived token Secret (type kubernetes.io/service-account-token with kubernetes.io/service-account-name annotation) or a bound token.","Confirm argo-server RBAC grants `get secrets` in the namespace.","Recreate the ServiceAccount to regenerate a token secret on older clusters.","If using projected tokens is intentional, this legacy webhook-auth path requires a static token secret — provision one manually.","Read the wrapped error in server logs to separate NotFound from Forbidden."],"exampleFix":"# k8s >=1.24: create a static token secret for the SA\napiVersion: v1\nkind: Secret\nmetadata:\n  name: my-sa-token\n  namespace: <ns>\n  annotations:\n    kubernetes.io/service-account.name: my-sa\ntype: kubernetes.io/service-account-token","handlingStrategy":"validation","validationCode":"sa, _ := clientset.CoreV1().ServiceAccounts(ns).Get(ctx, saName, metav1.GetOptions{})\ntokName := saName + \"-token\"\nif _, err := clientset.CoreV1().Secrets(ns).Get(ctx, tokName, metav1.GetOptions{}); err != nil {\n\treturn fmt.Errorf(\"token secret %q missing for SA: %w\", tokName, err)\n}","typeGuard":null,"tryCatchPattern":"secret, err := clientset.CoreV1().Secrets(ns).Get(ctx, secrets.TokenNameForServiceAccount(sa), metav1.GetOptions{})\nif errors.IsNotFound(err) {\n\t// k8s >=1.24: create a static service-account-token Secret\n} else if err != nil {\n\t// check RBAC get secrets\n}","preventionTips":["On k8s >=1.24 explicitly create a long-lived token Secret per webhook SA","Grant argo-server `get secrets` in webhook namespaces","Exclude `<sa>-token` secrets from secret-cleanup jobs","Alert on missing token secrets for SAs referenced in webhook-clients"],"tags":["kubernetes","secrets","serviceaccount","webhook","authentication"],"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"}