argoproj/argo-workflows · error

unable to parse argo variable: %w

Error message

unable to parse argo variable: %w

What it means

expandStep marshals the step template to JSON and runs template.NewTemplate to validate/parse its argo variables. If the template syntax is invalid (unbalanced braces, malformed {{...}} expressions), expansion of withItems/withParam fails with this wrapped parse error.

Source

Thrown at workflow/controller/steps.go:646

		}
	default:
		// this should have been prevented in expandStepGroup()
		return nil, argoerrors.InternalError("expandStep() was called with withItems and withParam empty")
	}

	// these fields can be very large (>100m) and marshalling 10k x 100m = 6GB of memory used and
	// very poor performance, so we just nil them out
	step.WithItems = nil
	step.WithParam = ""
	step.WithSequence = nil

	stepBytes, err := json.Marshal(step)
	if err != nil {
		return nil, argoerrors.InternalWrapError(err)
	}
	t, err := template.NewTemplate(string(stepBytes))
	if err != nil {
		return nil, fmt.Errorf("unable to parse argo variable: %w", err)
	}

	for i, item := range items {
		var newStep wfv1.WorkflowStep
		newStepName, err := processItem(ctx, t, step.Name, i, item, &newStep, step.When, scope.getParametersAny(woc.globalParams()))
		if err != nil {
			return nil, err
		}
		newStep.Name = newStepName
		newStep.Template = step.Template
		expandedStep = append(expandedStep, newStep)
	}
	return expandedStep, nil
}

func (woc *wfOperationCtx) prepareDefaultMetricScope() (map[string]any, map[string]func() float64) {
	localScope := template.ToAnyMap(woc.globalParams())
	localScope[varkeys.MetricDuration.Template()] = "0"

View on GitHub (pinned to 35bff19146)

Solutions

  1. Fix the malformed {{...}} expression in the step template
  2. Validate the workflow with argo lint before submitting
  3. Escape literal braces or move complex expressions into scripts

Example fix

// before
- name: fanout
  template: echo
  withItems: [1, 2]
  arguments:
    parameters:
      - name: msg
        value: 'hello {{item}} }' # unbalanced brace
// after
  arguments:
    parameters:
      - name: msg
        value: 'hello {{item}}'
Defensive patterns

Strategy: validation

Validate before calling

// check for balanced braces in templated strings before submit
func balancedBraces(s string) bool { c := 0; for _, r := range s { if r=='{' {c++}; if r=='}' {c--}; if c>1||c<0 {return false} }; return c==0 }

Try / catch

if strings.Contains(err.Error(), "unable to parse argo variable") {
    // fix malformed {{...}} in the step template and resubmit
}

Prevention

When it happens

Trigger: expandStep on a step using withItems/withMap/withParam where the step's templated strings contain malformed argo variable syntax that template.NewTemplate cannot parse.

Common situations: Unbalanced {{ }} braces, stray single braces, invalid expression syntax inside item loops; YAML anchors producing odd strings; typos like {{item}} misspellings.

Understand the failure class

Related errors


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