argoproj/argo-workflows · error

failed to evaluate expression %q

Error message

failed to evaluate expression %q

What it means

expressionReplaceCore wraps the error from compiling/running the expr-lang expression after unmarshalling it, when failures are not permitted (allowUnresolved and shouldAllowFailure are both false). It fires during strict expression template resolution when the expression is syntactically invalid, references unknown env fields, or raises a runtime error, quoting the original expression.

Source

Thrown at util/template/expression_template.go:258

	program, err := expr.Compile(unmarshalledExpression, expr.Env(env))
	// This allowUnresolved check is not great
	// it allows for errors that are obviously
	// not failed reference checks to also pass
	if err != nil && !allowUnresolved && !shouldAllowFailure {
		return 0, fmt.Errorf("failed to evaluate expression: %w", err)
	}
	result, err := expr.Run(program, env)
	if (err != nil || result == nil) && (allowUnresolved || shouldAllowFailure) {
		//  <nil> result is also un-resolved, and any error can be unresolved
		log.WithError(err).Debug(ctx, "Result and error are unresolved")
		return fmt.Fprintf(w, "{{%s%s}}", kindExpression, expression)
	}
	if err != nil {
		return 0, fmt.Errorf("failed to evaluate expression: %w", err)
	}
	if result == nil {
		return 0, fmt.Errorf("failed to evaluate expression %q", expression)
	}
	resultMarshaled, err := json.Marshal(result)
	if (err != nil || resultMarshaled == nil) && allowUnresolved {
		log.WithError(err).Debug(ctx, "resultMarshaled is nil and unresolved is allowed ")
		return fmt.Fprintf(w, "{{%s%s}}", kindExpression, expression)
	}
	if err != nil {
		return 0, fmt.Errorf("failed to marshal evaluated expression: %w", err)
	}
	if resultMarshaled == nil {
		return 0, fmt.Errorf("failed to marshal evaluated marshaled expression %q", expression)
	}
	marshaledLength := len(resultMarshaled)

	// Trim leading and trailing quotes. The value is being inserted into something that's already a string.
	if len(resultMarshaled) > 1 && resultMarshaled[0] == '"' && resultMarshaled[marshaledLength-1] == '"' {
		return w.Write(resultMarshaled[1 : marshaledLength-1])
	}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Make the expression produce a concrete value (guard nils with sprig-like defaults or conditional logic)
  2. Ensure referenced outputs actually exist before this template runs
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at util/template/expression_template.go:258 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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