nektos/act · error

unable to read workflow '%s': file is empty: %w

Error message

unable to read workflow '%s': file is empty: %w

What it means

Returned by NewWorkflowPlanner when ReadWorkflow on a .yml/.yaml file in .github/workflows returns io.EOF, meaning the file is completely empty. The planner scans every YAML file in the directory, so a single empty file aborts planning.

Source

Thrown at pkg/model/planner.go:131

			workflowDirEntry: fs.FileInfoToDirEntry(fi),
		})
	}

	wp := new(workflowPlanner)
	for _, wf := range workflows {
		ext := filepath.Ext(wf.workflowDirEntry.Name())
		if ext == ".yml" || ext == ".yaml" {
			f, err := os.Open(filepath.Join(wf.dirPath, wf.workflowDirEntry.Name()))
			if err != nil {
				return nil, err
			}

			log.Debugf("Reading workflow '%s'", f.Name())
			workflow, err := ReadWorkflow(f, strict)
			if err != nil {
				_ = f.Close()
				if err == io.EOF {
					return nil, fmt.Errorf("unable to read workflow '%s': file is empty: %w", wf.workflowDirEntry.Name(), err)
				}
				return nil, fmt.Errorf("workflow is not valid. '%s': %w", wf.workflowDirEntry.Name(), err)
			}
			_, err = f.Seek(0, 0)
			if err != nil {
				_ = f.Close()
				return nil, fmt.Errorf("error occurring when resetting io pointer in '%s': %w", wf.workflowDirEntry.Name(), err)
			}

			workflow.File = wf.workflowDirEntry.Name()
			if workflow.Name == "" {
				workflow.Name = wf.workflowDirEntry.Name()
			}

			err = validateJobName(workflow)
			if err != nil {
				_ = f.Close()
				return nil, err

View on GitHub (pinned to 4f41128141)

Solutions

  1. Delete or populate the empty .yml/.yaml file in .github/workflows.
  2. Run `find .github/workflows -name '*.yml' -empty` to locate the offending file.
  3. Add minimal valid content (name, on, jobs) if the file is intentionally kept.

Example fix

# delete the empty file
rm .github/workflows/empty.yml
# or give it minimal content
name: placeholder
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo ok
Defensive patterns

Strategy: validation

Validate before calling

// guard: reject empty workflow files before planning
entries, _ := os.ReadDir(".github/workflows")
for _, e := range entries {
    if strings.HasSuffix(e.Name(), ".yml") || strings.HasSuffix(e.Name(), ".yaml") {
        if fi, _ := e.Info(); fi.Size() == 0 {
            return fmt.Errorf("%s is empty", e.Name())
        }
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "file is empty") {
    // locate and delete/fill the named file, then re-run
}

Prevention

When it happens

Trigger: An empty .github/workflows/*.yml file exists (created by touch, a failed editor save, or a template placeholder). os.Open succeeds, ReadWorkflow hits EOF on the first read, and the planner wraps it with this message.

Common situations: Leftover placeholder files like `.github/workflows/tmp.yml`; CI scaffolding that creates files before filling them; a commit that accidentally emptied a workflow file.

Related errors


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