nektos/act · error
❌ Error in if-expression: "if: %s" (%s)
Error message
❌ Error in if-expression: "if: %s" (%s)
What it means
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.
Source
Thrown at pkg/runner/run_context.go:800
func (rc *RunContext) options(ctx context.Context) string {
job := rc.Run.Job()
c := job.Container()
if c != nil {
return rc.ExprEval.Interpolate(ctx, c.Options)
}
return rc.Config.ContainerOptions
}
func (rc *RunContext) isEnabled(ctx context.Context) (bool, error) {
job := rc.Run.Job()
l := common.Logger(ctx)
runJob, runJobErr := EvalBool(ctx, rc.ExprEval, job.If.Value, exprparser.DefaultStatusCheckSuccess)
jobType, jobTypeErr := job.Type()
if runJobErr != nil {
return false, fmt.Errorf(" \u274C Error in if-expression: \"if: %s\" (%s)", job.If.Value, runJobErr)
}
if jobType == model.JobTypeInvalid {
return false, jobTypeErr
}
if !runJob {
rc.result("skipped")
l.WithField("jobResult", "skipped").Debugf("Skipping job '%s' due to '%s'", job.Name, job.If.Value)
return false, nil
}
if jobType != model.JobTypeDefault {
return true, nil
}
img := rc.platformImage(ctx)
if img == "" {View on GitHub (pinned to 4f41128141)
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).
Example fix
# before
jobs:
deploy:
if: ${{ steps.build.outputs.ok == 'true' }} # 'steps' undefined at job level
# after
jobs:
deploy:
needs: build
if: ${{ needs.build.outputs.ok == 'true' }} Defensive patterns
Strategy: validation
Validate before calling
# CI step: validate workflow expressions before execution - run: actionlint -shellcheck= -pyflakes= .github/workflows/*.yml
Prevention
- 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.
When it happens
Trigger: `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()`.
Common situations: 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.
Related errors
- ❌ Error in if-expression: "if: %s" (%s)
- ❌ Error in continue-on-error-expression: "continue-on-err
- Expected format {org}/{repo}[/path]@ref. Actual '%s' Input s
- Invalid run/uses syntax for job:%s step:%+v
- ErrShortRef
AI-assisted analysis of nektos/act@4f41128141 (2026-08-15).
Data as JSON: /api/errors/920915c23f30bce3.
Report an issue: GitHub.