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
- Check the wrapped cause (%w) in the controller log for the expr parse/eval error detail
- Ensure the expression is valid expr-lang syntax and evaluates to a bool
- Reference only variables provided in the evaluation environment (see docs on CronWorkflow stopStrategy)
- 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
- Compile expressions in CI with expr.AsBool to catch syntax/type errors early
- Only reference identifiers documented for stopStrategy environments
- Add a canary CronWorkflow when introducing new expressions
- Keep a lint step (argo lint + custom expr check) in your GitOps pipeline
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
- failed to check CronWorkflow '%s' stopping condition: %w
- single branch mode without a branch specified
- unable to delete Successful Workflows of CronWorkflow '%s':
- unable to delete Failed Workflows of CronWorkflow '%s': %w
- unable to process data transformation: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/e63d06b4689da441.
Report an issue: GitHub.