nektos/act · error

%sFailed to parse: %s

Error message

%sFailed to parse: %s

What it means

Error from Node.checkExpression (schema.go:218) when the text following a `${{` marker cannot be parsed as a valid expression by actionlint's expression parser. The location (line/column of the YAML node) is prefixed to the parser's message.

Source

Thrown at pkg/schema/schema.go:218

}

func (s *Node) checkExpression(node *yaml.Node) (bool, error) {
	val := node.Value
	hadExpr := false
	var err error
	for {
		if i := strings.Index(val, "${{"); i != -1 {
			val = val[i+3:]
		} else {
			return hadExpr, err
		}
		hadExpr = true

		parser := actionlint.NewExprParser()
		lexer := actionlint.NewExprLexer(val)
		exprNode, parseErr := parser.Parse(lexer)
		if parseErr != nil {
			err = errors.Join(err, fmt.Errorf("%sFailed to parse: %s", formatLocation(node), parseErr.Message))
			continue
		}
		val = val[lexer.Offset():]
		cerr := s.checkSingleExpression(exprNode)
		if cerr != nil {
			err = errors.Join(err, fmt.Errorf("%s%w", formatLocation(node), cerr))
		}
	}
}

func AddFunction(funcs *[]FunctionInfo, s string, i1, i2 int) {
	*funcs = append(*funcs, FunctionInfo{
		name: s,
		min:  i1,
		max:  i2,
	})
}

View on GitHub (pinned to 4f41128141)

Solutions

  1. Read the parser message after 'Failed to parse:' — it names the syntax problem and position
  2. Fix the expression between ${{ and }} (balance parens, remove stray tokens)
  3. Check YAML quoting: inside single quotes escape ' as '' and avoid double-substitution
  4. Paste the expression into actionlint or the GitHub expression docs to verify syntax

Example fix

# before:
if: ${{ env.FLAG == 'true' && (github.ref
# after:
if: ${{ env.FLAG == 'true' && github.ref == 'refs/heads/main' }}
Defensive patterns

Strategy: validation

Validate before calling

// Keep a template-free pipeline: assert generated YAML contains no leftover '{{' or stray tokens before validation
if strings.Contains(rendered, "{{") || strings.Count(expr, "(") != strings.Count(expr, ")") {
    return errors.New("possibly malformed expression in rendered workflow")
}

Try / catch

Collect the joined parse errors, print all locations, fix the YAML; deterministic failure, no retry.

Prevention

When it happens

Trigger: Malformed expression syntax after ${{: unbalanced parentheses, stray operators, or leftover text like ${{ env.NAME extra }}. The loop finds each ${{ and parses everything up to the closing }}; a parse failure joins this error and continues scanning.

Common situations: Typos in complex expressions; YAML quoting issues that mangle ${{ }} (e.g. single-quote escaping turning '' into content); templating tools that partially substitute values leaving invalid syntax.

Understand the failure class

Related errors


AI-assisted analysis of nektos/act@4f41128141 (2026-08-15). Data as JSON: /api/errors/c9343bd80a1f0be6. Report an issue: GitHub.