{"record":{"id":"307c2d3acac73259","repo":"nektos/act","slug":"unable-to-read-workflow-s-file-is-empty-w","errorCode":null,"errorMessage":"unable to read workflow '%s': file is empty: %w","messagePattern":"unable to read workflow '(.+?)': file is empty: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/model/planner.go","lineNumber":131,"sourceCode":"\t\t\tworkflowDirEntry: fs.FileInfoToDirEntry(fi),\n\t\t})\n\t}\n\n\twp := new(workflowPlanner)\n\tfor _, wf := range workflows {\n\t\text := filepath.Ext(wf.workflowDirEntry.Name())\n\t\tif ext == \".yml\" || ext == \".yaml\" {\n\t\t\tf, err := os.Open(filepath.Join(wf.dirPath, wf.workflowDirEntry.Name()))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tlog.Debugf(\"Reading workflow '%s'\", f.Name())\n\t\t\tworkflow, err := ReadWorkflow(f, strict)\n\t\t\tif err != nil {\n\t\t\t\t_ = f.Close()\n\t\t\t\tif err == io.EOF {\n\t\t\t\t\treturn nil, fmt.Errorf(\"unable to read workflow '%s': file is empty: %w\", wf.workflowDirEntry.Name(), err)\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"workflow is not valid. '%s': %w\", wf.workflowDirEntry.Name(), err)\n\t\t\t}\n\t\t\t_, err = f.Seek(0, 0)\n\t\t\tif err != nil {\n\t\t\t\t_ = f.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"error occurring when resetting io pointer in '%s': %w\", wf.workflowDirEntry.Name(), err)\n\t\t\t}\n\n\t\t\tworkflow.File = wf.workflowDirEntry.Name()\n\t\t\tif workflow.Name == \"\" {\n\t\t\t\tworkflow.Name = wf.workflowDirEntry.Name()\n\t\t\t}\n\n\t\t\terr = validateJobName(workflow)\n\t\t\tif err != nil {\n\t\t\t\t_ = f.Close()\n\t\t\t\treturn nil, err","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/model/planner.go#L113-L149","documentation":"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.","triggerScenarios":"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.","commonSituations":"Leftover placeholder files like `.github/workflows/tmp.yml`; CI scaffolding that creates files before filling them; a commit that accidentally emptied a workflow file.","solutions":["Delete or populate the empty .yml/.yaml file in .github/workflows.","Run `find .github/workflows -name '*.yml' -empty` to locate the offending file.","Add minimal valid content (name, on, jobs) if the file is intentionally kept."],"exampleFix":"# delete the empty file\nrm .github/workflows/empty.yml\n# or give it minimal content\nname: placeholder\non: push\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - run: echo ok","handlingStrategy":"validation","validationCode":"// guard: reject empty workflow files before planning\nentries, _ := os.ReadDir(\".github/workflows\")\nfor _, e := range entries {\n    if strings.HasSuffix(e.Name(), \".yml\") || strings.HasSuffix(e.Name(), \".yaml\") {\n        if fi, _ := e.Info(); fi.Size() == 0 {\n            return fmt.Errorf(\"%s is empty\", e.Name())\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"file is empty\") {\n    // locate and delete/fill the named file, then re-run\n}","preventionTips":["Add a CI check that .github/workflows contains no zero-byte YAML files.","Never leave touch-created placeholder workflows in the tree.","Use yamllint in CI; it also flags empty files."],"tags":["workflow","planner","yaml","empty-file"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}