{"record":{"id":"6923d2b95e523e52","repo":"nektos/act","slug":"error-in-continue-on-error-expression-conti","errorCode":null,"errorMessage":"  ❌  Error in continue-on-error-expression: \"continue-on-error: %s\" (%s)","messagePattern":"  ❌  Error in continue-on-error-expression: \"continue-on-error: (.+?)\" \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runner/step.go","lineNumber":325,"sourceCode":"\trunStep, err := EvalBool(ctx, rc.NewStepExpressionEvaluatorExt(ctx, step, stage == stepStageMain), expr, defaultStatusCheck)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"  \\u274C  Error in if-expression: \\\"if: %s\\\" (%s)\", expr, err)\n\t}\n\n\treturn runStep, nil\n}\n\nfunc isContinueOnError(ctx context.Context, expr string, step step, _ stepStage) (bool, error) {\n\t// https://github.com/github/docs/blob/3ae84420bd10997bb5f35f629ebb7160fe776eae/content/actions/reference/workflow-syntax-for-github-actions.md?plain=true#L962\n\tif len(strings.TrimSpace(expr)) == 0 {\n\t\treturn false, nil\n\t}\n\n\trc := step.getRunContext()\n\n\tcontinueOnError, err := EvalBool(ctx, rc.NewStepExpressionEvaluator(ctx, step), expr, exprparser.DefaultStatusCheckNone)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"  \\u274C  Error in continue-on-error-expression: \\\"continue-on-error: %s\\\" (%s)\", expr, err)\n\t}\n\n\treturn continueOnError, nil\n}\n\nfunc mergeIntoMap(step step, target *map[string]string, maps ...map[string]string) {\n\tif rc := step.getRunContext(); rc != nil && rc.JobContainer != nil && rc.JobContainer.IsEnvironmentCaseInsensitive() {\n\t\tmergeIntoMapCaseInsensitive(*target, maps...)\n\t} else {\n\t\tmergeIntoMapCaseSensitive(*target, maps...)\n\t}\n}\n\nfunc mergeIntoMapCaseSensitive(target map[string]string, maps ...map[string]string) {\n\tfor _, m := range maps {\n\t\tfor k, v := range m {\n\t\t\ttarget[k] = v\n\t\t}","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/runner/step.go#L307-L343","documentation":"A step's `continue-on-error:` value could not be evaluated as a boolean expression. isContinueOnError skips empty values but runs anything else through EvalBool with DefaultStatusCheckNone; non-boolean results or evaluation errors (bad syntax, unknown context) produce this error.","triggerScenarios":"`continue-on-error: ${{ ... }}` where the expression returns a non-boolean (string/number) that the evaluator refuses, references undefined contexts, or contains a syntax error; also plain strings that aren't valid expressions after implicit conversion rules.","commonSituations":"Setting `continue-on-error: ${{ steps.check.outputs.retry }}` where output is 'yes'/'no' instead of 'true'/'false'; complex ternary expressions with typos; referencing contexts not available at that point in evaluation.","solutions":["Make the expression strictly boolean: compare strings explicitly (`== 'true'`) instead of relying on truthiness of arbitrary strings.","Verify function names and context availability at step scope.","Test by temporarily replacing the expression with a literal true/false to confirm the rest of the step works."],"exampleFix":"# before\ncontinue-on-error: ${{ steps.setup.outputs.retrying }}   # 'yes' is not boolean\n# after\ncontinue-on-error: ${{ steps.setup.outputs.retrying == 'yes' }}","handlingStrategy":"validation","validationCode":"# ensure continue-on-error is boolean-valued: prefer\n#   continue-on-error: ${{ expr == 'value' }}\n# never a bare non-boolean output reference","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always wrap string outputs in an explicit == comparison.","Test expressions with a literal true first.","actionlint catches malformed expressions here too."],"tags":["expressions","continue-on-error","steps","validation"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}