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

  1. Create the missing service account: `kubectl create serviceaccount <name> -n <workflow-namespace>`
  2. Correct spec.serviceAccountName in the workflow to an existing SA in the workflow's namespace
  3. Check the wrapped inner error to distinguish 'not found' from RBAC/API failure
  4. 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

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


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/e4dc07b95198b7db. Report an issue: GitHub.