nektos/act · error
Unable to Close file: %v
Error message
Unable to Close file: %v
What it means
Thrown by act's expression interpreter when actionlint's expression parser fails to parse the text inside ${{ }}. The message embeds actionlint's own parse error, which names the offending token and column. This is a syntax-level failure in the GitHub Actions expression language.
Source
Thrown at pkg/exprparser/functions.go:237
if len(files) == 0 {
return "", nil
}
hasher := sha256.New()
for _, file := range files {
f, err := os.Open(file)
if err != nil {
return "", fmt.Errorf("Unable to os.Open: %v", err)
}
if _, err := io.Copy(hasher, f); err != nil {
return "", fmt.Errorf("Unable to io.Copy: %v", err)
}
if err := f.Close(); err != nil {
return "", fmt.Errorf("Unable to Close file: %v", err)
}
}
return hex.EncodeToString(hasher.Sum(nil)), nil
}
func (impl *interperterImpl) getNeedsTransitive(job *model.Job) []string {
needs := job.Needs()
for _, need := range needs {
parentNeeds := impl.getNeedsTransitive(impl.config.Run.Workflow.GetJob(need))
needs = append(needs, parentNeeds...)
}
return needs
}
func (impl *interperterImpl) always() (bool, error) {View on GitHub (pinned to 4f41128141)
Solutions
- Read the embedded parser message — it points to the exact token and column.
- Simplify the expression or move logic into the run: script.
- Lint the workflow with actionlint to catch it statically.
- Compare against GitHub's expression syntax docs; no shell constructs allowed inside ${{ }}.
Example fix
# before
${{ env.GREETING && echo hi }}
# after
${{ env.GREETING != '' && 'hi' || 'bye' }} Defensive patterns
Strategy: validation
Validate before calling
func expressionParses(expr string) bool {
_, err := actionlint.NewExprParser().Parse(actionlint.NewExprLexer(expr))
return err == nil
} Try / catch
if v, err := interp.Evaluate(raw, status); err != nil {
if strings.Contains(err.Error(), 'Failed to parse') {
// surface the actionlint message to the workflow author
return fmt.Errorf('bad expression %q: %w', raw, err)
}
return err
} Prevention
- Run actionlint in CI for every workflow change
- Keep shell logic out of ${{ }}
- Break long expressions into named env vars step by step
When it happens
Trigger: Typos like ${{ env. }} or ${{ if(x) }}; unbalanced parentheses/quotes; using shell syntax inside expressions ($(), backticks); missing '}}' terminator (act appends it, so inner stray '}}' breaks too).
Common situations: Converting shell logic into expressions; complex nested ternaries; copy-pasting from docs with smart quotes; older act versions being stricter/looser than GitHub.
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/62def5c5d4b0b528.
Report an issue: GitHub.