argoproj/argo-workflows · error

failed to substitute configMapKeyRef: %w

Error message

failed to substitute configMapKeyRef: %w

What it means

substituteConfigMapKeyRefParam resolves `{{workflow.parameters.X}}`-style expressions backed by a configMapKeyRef by first building a template and then running tmpl.Replace to substitute values. Any failure during that substitution (unresolvable variable, malformed template expression) is wrapped as 'failed to substitute configMapKeyRef: %w' so callers know the configMap parameter substitution stage failed.

Source

Thrown at workflow/common/util.go:267

			artifacts[i] = *argArt
			artifacts[i].Path = inArt.Path
			artifacts[i].Mode = inArt.Mode
			artifacts[i].RecurseMode = inArt.RecurseMode
		}
	}

	return SubstituteParams(ctx, newTmpl, globalParams, localParams)
}

// substituteConfigMapKeyRefParam performs template substitution for ConfigMapKeyRef
func substituteConfigMapKeyRefParam(ctx context.Context, in string, replaceMap map[string]any) (string, error) {
	tmpl, err := template.NewTemplate(in)
	if err != nil {
		return "", err
	}
	replacedString, err := tmpl.Replace(ctx, replaceMap, false)
	if err != nil {
		return "", fmt.Errorf("failed to substitute configMapKeyRef: %w", err)
	}
	return replacedString, nil
}

// SubstituteParams returns a new copy of the template with global, pod, and input parameters substituted
func SubstituteParams(ctx context.Context, tmpl *wfv1.Template, globalParams, localParams Parameters) (*wfv1.Template, error) {
	tmplBytes, err := json.Marshal(tmpl)
	if err != nil {
		return nil, errors.InternalWrapError(err)
	}
	// First replace globals & locals, then replace inputs because globals could be referenced in the inputs
	replaceMap := template.ToAnyMap(globalParams.Merge(localParams))
	globalReplacedTmplStr, err := template.Replace(ctx, string(tmplBytes), replaceMap, true)
	if err != nil {
		return nil, err
	}
	var globalReplacedTmpl wfv1.Template
	err = json.Unmarshal([]byte(globalReplacedTmplStr), &globalReplacedTmpl)

View on GitHub (pinned to 35bff19146)

Solutions

  1. Read the wrapped inner error (%w chain) to find the exact unresolvable variable and fix the expression in the template/parameter
  2. Ensure the referenced ConfigMap key exists and its value contains only resolvable expressions (see error 540 for the label requirement)
  3. Validate the workflow with `argo lint` before submitting to catch malformed template expressions
  4. Check that all replaceMap parameters (global + local) are actually provided in spec.arguments

Example fix

# before
value: "{{workflow.parameters.missingParam}}/path"
# after
value: "{{workflow.parameters.definedParam}}/path"
Defensive patterns

Strategy: try-catch

Try / catch

replaced, err := common.SubstituteParams(ctx, tmpl, globalParams, localParams)
if err != nil {
    return fmt.Errorf("configMapKeyRef substitution failed: %w", err) // inspect %w chain for the bad expression
}

Prevention

When it happens

Trigger: A workflow parameter/cron spec contains a configMapKeyRef whose value template references variables that cannot be resolved at substitute time, or the raw input (`in`) is not a valid template (template.NewTemplate fails), or tmpl.Replace encounters an undefined/ill-formed expression in replaceMap keys.

Common situations: Referencing a global parameter inside a configMapKeyRef value before it exists; typos like `{{workflow.name` (unclosed braces); submitting a CronWorkflow whose `when`/parameter expressions reference the schedule or event placeholders that aren't populated; calling SubstituteParams with local params missing a referenced key.

Related errors


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