{"record":{"id":"920915c23f30bce3","repo":"nektos/act","slug":"error-in-if-expression-if-s-s","errorCode":null,"errorMessage":"  ❌  Error in if-expression: \"if: %s\" (%s)","messagePattern":"  ❌  Error in if-expression: \"if: (.+?)\" \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runner/run_context.go","lineNumber":800,"sourceCode":"\nfunc (rc *RunContext) options(ctx context.Context) string {\n\tjob := rc.Run.Job()\n\tc := job.Container()\n\tif c != nil {\n\t\treturn rc.ExprEval.Interpolate(ctx, c.Options)\n\t}\n\n\treturn rc.Config.ContainerOptions\n}\n\nfunc (rc *RunContext) isEnabled(ctx context.Context) (bool, error) {\n\tjob := rc.Run.Job()\n\tl := common.Logger(ctx)\n\trunJob, runJobErr := EvalBool(ctx, rc.ExprEval, job.If.Value, exprparser.DefaultStatusCheckSuccess)\n\tjobType, jobTypeErr := job.Type()\n\n\tif runJobErr != nil {\n\t\treturn false, fmt.Errorf(\"  \\u274C  Error in if-expression: \\\"if: %s\\\" (%s)\", job.If.Value, runJobErr)\n\t}\n\n\tif jobType == model.JobTypeInvalid {\n\t\treturn false, jobTypeErr\n\t}\n\n\tif !runJob {\n\t\trc.result(\"skipped\")\n\t\tl.WithField(\"jobResult\", \"skipped\").Debugf(\"Skipping job '%s' due to '%s'\", job.Name, job.If.Value)\n\t\treturn false, nil\n\t}\n\n\tif jobType != model.JobTypeDefault {\n\t\treturn true, nil\n\t}\n\n\timg := rc.platformImage(ctx)\n\tif img == \"\" {","sourceCodeStart":782,"sourceCodeEnd":818,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/runner/run_context.go#L782-L818","documentation":"The job-level `if:` expression could not be evaluated. EvalBool runs the expression through act's exprparser; a syntax error, unknown function/context, or type error inside the `${{ }}` expression causes the parser to return an error, which act surfaces prefixed with the failing expression text.","triggerScenarios":"`jobs.<id>.if:` contains invalid expression syntax (unbalanced parens, bad operator), references a context or property not available at job level (e.g. steps context, which only exists for steps), uses an undefined function, or has a typo like `falsy()` instead of `always()`.","commonSituations":"Copy-pasting a step-level `if: ${{ steps.check.outputs.x }}` to the job level where `steps` does not exist; typos in function names; using runner.* or env.* properties that are not implemented in act; expressions valid on GitHub but relying on contexts act does not populate.","solutions":["Read the parenthesized inner error — it names the exact parse/eval failure for the printed expression.","Move step-scoped contexts (steps, needs outputs are fine at job level but steps are not) out of job-level `if:`; use `needs.<job>.outputs.*` instead.","Validate expression syntax with actionlint, which understands GitHub's expression grammar.","Simplify the expression to isolate the failing token (e.g. test `if: true` first, then add pieces back)."],"exampleFix":"# before\njobs:\n  deploy:\n    if: ${{ steps.build.outputs.ok == 'true' }}  # 'steps' undefined at job level\n# after\njobs:\n  deploy:\n    needs: build\n    if: ${{ needs.build.outputs.ok == 'true' }}","handlingStrategy":"validation","validationCode":"# CI step: validate workflow expressions before execution\n- run: actionlint -shellcheck= -pyflakes= .github/workflows/*.yml","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only use job-level contexts in job-level if (github, needs, vars, inputs).","Run actionlint in CI to catch expression errors.","Test complex conditions in a scratch workflow first."],"tags":["expressions","workflow-syntax","if-condition","validation"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}