argoproj/argo-workflows · error

failed to evaluate stop expression: %w

Error message

failed to evaluate stop expression: %w

What it means

The stop expression configured on a CronWorkflow's spec.stopStrategy could not be evaluated as a boolean by the expr language evaluator (argoexpr.EvalBool). checkStopingCondition builds an environment (e.g. cronWorkflow schedule data) and evaluates the expression; any evaluation failure is wrapped with this message.

Source

Thrown at workflow/cron/operator.go:559

	}
	prefixedEnv := make(map[string]any)
	prefix := variablePrefix + "."
	setField := func(name string, value any) {
		// `name` is the canonical "cronworkflow.X". Strip the
		// "cronworkflow." prefix because we expose the inner map under the
		// "cronworkflow" key for expr-lang member access.
		prefixedEnv[strings.TrimPrefix(name, prefix)] = value
	}
	env := make(map[string]any)
	env[variablePrefix] = prefixedEnv
	err := expressionEnv(woc.cronWf, setField)
	if err != nil {
		return false, err
	}

	suspend, err := argoexpr.EvalBool(woc.cronWf.Spec.StopStrategy.Expression, env)
	if err != nil {
		return false, fmt.Errorf("failed to evaluate stop expression: %w", err)
	}
	return suspend, nil
}

func (woc *cronWfOperationCtx) setAsCompleted() {
	woc.cronWf.Status.Phase = v1alpha1.StoppedPhase
	if woc.cronWf.Labels == nil {
		woc.cronWf.Labels = map[string]string{}
	}
	woc.cronWf.Labels[common.LabelKeyCronWorkflowCompleted] = "true"
}

func inferScheduledTime(ctx context.Context) time.Time {
	// Infer scheduled runtime by getting current time and zeroing out current seconds and nanoseconds
	// This works because the finest possible scheduled runtime is a minute. It is unlikely to ever be used, since this
	// function is quickly supplanted by a deterministic function from the cron engine.
	now := time.Now().UTC()
	scheduledTime := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), 0, 0, now.Location())

View on GitHub (pinned to 35bff19146)

Solutions

  1. Check the wrapped cause (%w) in the controller log for the expr parse/eval error detail
  2. Ensure the expression is valid expr-lang syntax and evaluates to a bool
  3. Reference only variables provided in the evaluation environment (see docs on CronWorkflow stopStrategy)
  4. Test the expression with expr-lang's REPL or a unit test before deploying

Example fix

// before
stopStrategy:
  expression: scheduledTime  // non-boolean
// after
stopStrategy:
  expression: cronWorkflow.lastScheduledTime.After(now()) == true
Defensive patterns

Strategy: validation

Validate before calling

// Validate before apply: must parse and return bool
program, err := expr.Compile(cronWf.Spec.StopStrategy.Expression,
    expr.Env(stopEnv), expr.AsBool())
if err != nil {
    return fmt.Errorf("stopStrategy.expression invalid: %w", err)
}

Prevention

When it happens

Trigger: spec.stopStrategy.expression is syntactically invalid, references an unknown variable in the environment, compares mismatched types, or does not evaluate to a bool.

Common situations: Copy-pasted expressions using the wrong variable names, using an expression from older docs with renamed fields, or non-boolean expressions like arithmetic results.

Related errors


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