nektos/act · warning
Failed to parse: %s
Error message
Failed to parse: %s
What it means
Thrown when an expression references the 'jobs' context but impl.env.Jobs is nil. act only populates the jobs context in specific positions (outputs of reusable-workflow callers / workflow-level expressions); elsewhere it is unavailable and this error fires instead of returning empty data.
Source
Thrown at pkg/exprparser/interpreter.go:89
config Config
}
func NewInterpeter(env *EvaluationEnvironment, config Config) Interpreter {
return &interperterImpl{
env: env,
config: config,
}
}
func (impl *interperterImpl) Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (interface{}, error) {
input = strings.TrimPrefix(input, "${{")
if defaultStatusCheck != DefaultStatusCheckNone && input == "" {
input = "success()"
}
parser := actionlint.NewExprParser()
exprNode, err := parser.Parse(actionlint.NewExprLexer(input + "}}"))
if err != nil {
return nil, fmt.Errorf("Failed to parse: %s", err.Message)
}
if defaultStatusCheck != DefaultStatusCheckNone {
hasStatusCheckFunction := false
actionlint.VisitExprNode(exprNode, func(node, _ actionlint.ExprNode, entering bool) {
if funcCallNode, ok := node.(*actionlint.FuncCallNode); entering && ok {
switch strings.ToLower(funcCallNode.Callee) {
case "success", "always", "cancelled", "failure":
hasStatusCheckFunction = true
}
}
})
if !hasStatusCheckFunction {
exprNode = &actionlint.LogicalOpNode{
Kind: actionlint.LogicalOpNodeKindAnd,
Left: &actionlint.FuncCallNode{
Callee: defaultStatusCheck.String(),View on GitHub (pinned to 4f41128141)
Solutions
- Access jobs.* only where GitHub documents it (workflow-level outputs wiring, caller-side expressions).
- Pass values explicitly via outputs/inputs instead of reading the jobs context downstream.
- Update act — jobs-context support for reusable workflows has improved across versions.
- If unsupported in act, guard with a contains-style check or move logic to the caller workflow.
Example fix
# before (inside reusable workflow step)
run: echo ${{ jobs.build.outputs.img }}
# after (wire through outputs)
jobs:
build:
outputs:
img: ${{ steps.b.out }}
call:
uses: ./.github/workflows/child.yml Defensive patterns
Strategy: validation
Validate before calling
func jobsContextAvailable(env *exprparser.ExpressionEnvLoading) bool {
return env.Jobs != nil // mirror the interpreter's own nil check
} Try / catch
if v, err := interp.Evaluate('${{ jobs.build.result }}', 0); err != nil {
if strings.Contains(err.Error(), 'Unavailable context: jobs') {
v = 'skipped' // not a caller-side evaluation: use a default
} else { return err }
} Prevention
- Read jobs.* only in caller workflows / output wiring
- Pass reusable-workflow results through outputs, not the jobs context downstream
- Keep act updated for reusable-workflow context support
When it happens
Trigger: Using jobs.<id>.outputs or jobs.<id>.result in a place act does not support (e.g. inside a reusable workflow's own steps, or a run where the jobs env was never wired up); referencing jobs in a locally triggered event that GitHub itself would not populate it for.
Common situations: Reusable workflows evaluated locally with act; expressions valid on github.com but hitting act's unsupported paths; typo'd context names that fall through to the generic unavailable-context case only when spelled 'jobs'.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- The following format string is invalid: '%s'
- The following format string references more arguments than w
- Unclosed brackets. The following format string is invalid: '
- Closing bracket without opening one. The following format st
- Cannot convert value to JSON. Cause: %v
AI-assisted analysis of nektos/act@4f41128141 (2026-08-15).
Data as JSON: /api/errors/9457894eba529335.
Report an issue: GitHub.