argoproj/argo-workflows · error
failed to get service account
Error message
failed to get service account "%s": %w
What it means
After a webhook request matches a client entry's secret parser, the interceptor looks up the named ServiceAccount in the ConfigMap's namespace via the Kubernetes API. This error is returned when that Get fails — most commonly the ServiceAccount does not exist (404), or the server lacks RBAC permission to read it. Without it the interceptor cannot fetch the token to impersonate the caller.
Solutions
- Verify the ServiceAccount exists: `kubectl get sa <name> -n <namespace>` (namespace is the one in the webhook URL).
- Recreate it if missing: `kubectl create sa <name> -n <namespace>` and attach the expected RBAC role for workflow submission.
- Make the webhook-clients ConfigMap key exactly match the ServiceAccount name.
- Check argo-server RBAC allows `get serviceaccounts` and `get secrets` in the namespace (`kubectl auth can-i get serviceaccounts -n <ns> --as=system:serviceaccount:<ns>:argo-server`).
- Inspect the wrapped %w error in the argo-server logs to distinguish NotFound from Forbidden.
Defensive patterns
Strategy: validation
Validate before calling
if _, err := clientset.CoreV1().ServiceAccounts(ns).Get(ctx, saName, metav1.GetOptions{}); err != nil {
return fmt.Errorf("webhook client SA %q missing: %w", saName, err)
}
ok, _ := kube.AuthCanI(clientset, "system:serviceaccount:argo:argo-server", "get", "serviceaccounts", ns) Try / catch
sa, err := clientset.CoreV1().ServiceAccounts(ns).Get(ctx, saName, metav1.GetOptions{})
if errors.IsNotFound(err) {
// recreate SA or fix ConfigMap key
} else if err != nil {
// check RBAC / API server reachability
} Prevention
- Ensure each webhook-clients key exactly equals an existing ServiceAccount name
- Deploy the SA together with the ConfigMap in the same manifest/Helm release
- Grant argo-server get on serviceaccounts in webhook namespaces
- Diff ConfigMap keys vs `kubectl get sa` in CI
When it happens
Trigger: Webhook request matched a webhook-clients entry whose key names a ServiceAccount that was deleted, renamed, exists in a different namespace than the event endpoint's namespace, or the argo-server service account lacks get on serviceaccounts in that namespace.
Common situations: Namespace recreated without the ServiceAccount; ConfigMap copied between namespaces keeping stale SA names; argo-server deployed with a ClusterRole missing `serviceaccounts` get; typo between the ConfigMap key and the actual SA name.
Related errors
- failed to get token secret
- failed to get token volumes
- failed to get webhook clients
- cannot get resource clusterWorkflowTemplate at cluster scope
- could not save to config map cache
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/c021b9c3273555a4.
Report an issue: GitHub.
Appendix: source
Thrown at server/auth/webhook/interceptor.go:103
if len(buf) > maxWebhookSize {
return fmt.Errorf("webhook request body exceeds maximum size of 2MB")
}
defer func() { r.Body = io.NopCloser(bytes.NewBuffer(buf)) }()
serviceAccountInterface := kube.CoreV1().ServiceAccounts(namespace)
for serviceAccountName, data := range webhookClients.Data {
r.Body = io.NopCloser(bytes.NewBuffer(buf))
client := &webhookClient{}
err := yaml.Unmarshal(data, client)
if err != nil {
return fmt.Errorf("failed to unmarshal webhook client \"%s\": %w", serviceAccountName, err)
}
i.logger.WithFields(logging.Fields{"serviceAccountName": serviceAccountName, "webhookType": client.Type}).Debug(r.Context(), "Attempting to match webhook request")
ok := webhookParsers[client.Type](client.Secret, r)
if ok {
i.logger.WithField("serviceAccountName", serviceAccountName).Debug(r.Context(), "Matched webhook request")
serviceAccount, err := serviceAccountInterface.Get(ctx, serviceAccountName, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("failed to get service account \"%s\": %w", serviceAccountName, err)
}
tokenSecret, err := secretsInterface.Get(ctx, secrets.TokenNameForServiceAccount(serviceAccount), metav1.GetOptions{})
if err != nil {
return fmt.Errorf("failed to get token secret \"%s\": %w", tokenSecret, err)
}
r.Header["Authorization"] = []string{"Bearer " + string(tokenSecret.Data["token"])}
return nil
}
}
return nil
}
View on GitHub (pinned to 35bff19146)