argoproj/argo-workflows · error
failed to get token volumes: %w
Error message
failed to get token volumes: %w
What it means
The Agent pod needs a projected ServiceAccount token volume so it can talk to the Kubernetes API (for HTTP templates with selfServeMode and plugins). createAgentPod calls getServiceAccountTokenVolume for the workflow's serviceAccountName; any failure (e.g. the service account does not exist) is wrapped as 'failed to get token volumes: %w'.
Source
Thrown at workflow/controller/agent.go:158
{Name: common.EnvVarWorkflowName, Value: woc.wf.Name},
{Name: common.EnvVarWorkflowUID, Value: string(woc.wf.UID)},
{Name: common.EnvAgentPatchRate, Value: env.LookupEnvStringOr(common.EnvAgentPatchRate, woc.controller.requeueTime.String())},
{Name: common.EnvVarPluginAddresses, Value: wfv1.MustMarshallJSON(addresses(pluginSidecars))},
{Name: common.EnvVarPluginNames, Value: wfv1.MustMarshallJSON(names(pluginSidecars))},
}
// If the default number of task workers is overridden, then pass it to the agent pod.
if taskWorkers, exists := os.LookupEnv(common.EnvAgentTaskWorkers); exists {
envVars = append(envVars, apiv1.EnvVar{
Name: common.EnvAgentTaskWorkers,
Value: taskWorkers,
})
}
serviceAccountName := woc.execWf.Spec.ServiceAccountName
tokenVolume, tokenVolumeMount, err := woc.getServiceAccountTokenVolume(ctx, serviceAccountName)
if err != nil {
return nil, fmt.Errorf("failed to get token volumes: %w", err)
}
podVolumes := slices.Concat(
pluginVolumes,
[]apiv1.Volume{volumeVarArgo, *tokenVolume},
)
podVolumeMounts := []apiv1.VolumeMount{
volumeMountVarArgo,
*tokenVolumeMount,
}
if certVolume != nil && certVolumeMount != nil {
podVolumes = append(podVolumes, *certVolume)
podVolumeMounts = append(podVolumeMounts, *certVolumeMount)
}
agentCtrTemplate := apiv1.Container{
Command: []string{"argoexec"},
Image: woc.controller.executorImage(),
ImagePullPolicy: woc.controller.executorImagePullPolicy(),View on GitHub (pinned to 35bff19146)
Solutions
- Create the missing service account: `kubectl create serviceaccount <name> -n <workflow-namespace>`
- Correct spec.serviceAccountName in the workflow to an existing SA in the workflow's namespace
- Check the wrapped inner error to distinguish 'not found' from RBAC/API failure
- Verify the SA exists: `kubectl get sa <name> -n <workflow-namespace>`
Example fix
# before spec: serviceAccountName: argo-wf-sa-typo # after spec: serviceAccountName: argo-wf-sa
Defensive patterns
Strategy: validation
Validate before calling
_, err := clientset.CoreV1().ServiceAccounts(ns).Get(ctx, saName, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
return fmt.Errorf("service account %s/%s does not exist", ns, saName)
} Prevention
- Validate spec.serviceAccountName exists in the workflow namespace before submitting (argo lint / admission policy)
- Protect SAs from deletion while workflows reference them
- Use a dedicated, namespaced SA per workflow namespace
When it happens
Trigger: Workflow spec sets spec.serviceAccountName to an SA that doesn't exist in the workflow namespace (or the token-volume lookup errors), while the controller builds the agent pod.
Common situations: Typo in serviceAccountName; SA defined only in another namespace; SA deleted by a cleanup job after the workflow was submitted; workflows referencing a default SA removed by cluster policy.
Related errors
- failed to list SSO RBAC service accounts: %w
- failed to get service account "%s": %w
- failed to get workflow template: %w
- failed to check if secret %s exists: %w
- cannot get resource clusterWorkflowTemplate at cluster scope
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/e4dc07b95198b7db.
Report an issue: GitHub.