argoproj/argo-workflows · error
failed to resolve references: %w
Error message
failed to resolve references: %w
What it means
resolveReferences resolves step inputs in parallel (goroutines reporting to errCh). After wg.Wait(), the first error collected is returned; unless it is ErrRequeue (transient, retried), it is wrapped as 'failed to resolve references'. It is the aggregate wrapper for any per-step input resolution failure.
Source
Thrown at workflow/controller/steps.go:569
errCh := make(chan error, len(stepGroup)) // contains the error during resolveStepReferences
var wg sync.WaitGroup
for i, step := range stepGroup {
parallelStepNum <- step.Name
wg.Go(func() {
if refErr := resolveStepReferences(i, step, newStepGroup); refErr != nil {
woc.log.WithFields(logging.Fields{"stepName": step.Name}).WithError(refErr).Error(ctx, "Failed to resolve references")
errCh <- refErr
}
<-parallelStepNum
})
}
wg.Wait()
if err := errorFromChannel(errCh); err != nil { // fetch the first error during resolveStepReferences
if errors.Is(err, ErrRequeue) {
return nil, err
}
return nil, fmt.Errorf("failed to resolve references: %w", err)
}
return newStepGroup, nil
}
// expandStepGroup looks at each step in a collection of parallel steps, and expands all steps using withItems/withParam
func (woc *wfOperationCtx) expandStepGroup(ctx context.Context, sgNodeName string, stepGroup []wfv1.WorkflowStep, stepsCtx *stepsContext) ([]wfv1.WorkflowStep, error) {
newStepGroup := make([]wfv1.WorkflowStep, 0)
for _, step := range stepGroup {
if !step.ShouldExpand() {
newStepGroup = append(newStepGroup, step)
continue
}
expandedStep, err := woc.expandStep(ctx, step, stepsCtx.scope)
if err != nil {
return nil, err
}
if len(expandedStep) == 0 {
// Empty listView on GitHub (pinned to 35bff19146)
Solutions
- Look at the wrapped inner error to find which step/reference failed
- Fix the referenced expression or mark inputs optional where appropriate
- If it's ErrRequeue-related (transient), the controller will retry automatically — check controller logs if it persists
Example fix
// before
- name: use
template: consume
arguments:
parameters:
- name: x
value: '{{steps.build.outputs.parameters.x}}' // build skipped -> unresolved
// after
- name: use
template: consume
when: '{{steps.build.status}} == Succeeded'
arguments:
parameters:
- name: x
value: '{{steps.build.outputs.parameters.x}}' Defensive patterns
Strategy: validation
Validate before calling
// validate expressions before submit argo lint my-wf.yaml
Try / catch
if strings.Contains(err.Error(), "failed to resolve references") {
// inspect wrapped cause to find the offending step/reference
} Prevention
- Lint workflows in CI
- Don't reference outputs of steps guarded by when without optionals/guards
- Keep variable names consistent with producer outputs
When it happens
Trigger: Any step in the group fails parameter/artifact reference resolution during expandStepGroup — e.g. unresolved {{steps.*}} expressions, missing outputs — and the error is not an ErrRequeue.
Common situations: Referencing outputs of a skipped or failed step; malformed template expressions; wrong variable names in inputs.parameters.value.
Related errors
- step group deemed errored due to child %s error: %w
- was unable to obtain childNode for %s
- unable to resolve references: %w
- unable to parse argo variable: %w
- failed to read container args file %s: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/03b655e59d0e0742.
Report an issue: GitHub.