nektos/act · error

failed to read ' ' from action ' ' with path ' ' of step

Error message

failed to read '%s' from action '%s' with path '%s' of step: %w

What it means

readActionImpl tries action.yml, then action.yaml, then Dockerfile when loading an action's metadata; each failed read is appended via addError. If no read succeeds, the accumulated errors are returned with this wrapper naming the step and actionPath. A single successful read clears the accumulated state, so this error means none of the metadata files could be read.

Solutions

  1. Verify the action repository actually contains action.yml or action.yaml at the referenced path (add the subdirectory in `uses:` for monorepos).
  2. Clear the action cache (`rm -rf ~/.cache/act` or the configured cache dir) and re-run so the action re-clones.
  3. Check credentials/permissions for private actions — a failed clone leaves an empty dir that produces this error.
  4. Pin a known-good tag/SHA of the action in `uses:`.

Example fix

# before
- uses: myorg/monorepo@v1
# after (metadata lives in subdir)
- uses: myorg/monorepo/subdir/action@v1
Defensive patterns

Strategy: validation

Validate before calling

func actionMetadataExists(dir string) bool {
    for _, f := range []string{"action.yml", "action.yaml", "Dockerfile"} {
        if _, err := os.Stat(filepath.Join(dir, f)); err == nil { return true }
    }
    return false
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to read 'action.yml'") {
    // check the action repo for metadata at the referenced path; clear the act cache and retry
}

Prevention

When it happens

Trigger: A remote action repository has no action.yml/action.yaml/Dockerfile at its root; a composite action's nested actionPath points at a subdirectory lacking metadata; the cloned action cache is incomplete after an interrupted fetch.

Common situations: Using an action whose repo renamed/moved metadata files; wrong `uses:` path for monorepo actions needing a subpath (e.g. missing `/subdir`); corrupted ~/.cache/act action downloads; private action fetched with bad credentials yielding empty dirs.

Related errors


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

Appendix: source

Thrown at pkg/runner/action.go:48

}

type readAction func(ctx context.Context, step *model.Step, actionDir string, actionPath string, readFile actionYamlReader, writeFile fileWriter) (*model.Action, error)

type actionYamlReader func(filename string) (io.Reader, io.Closer, error)

type fileWriter func(filename string, data []byte, perm fs.FileMode) error

type runAction func(step actionStep, actionDir string, remoteAction *remoteAction) common.Executor

//go:embed res/trampoline.js
var trampoline embed.FS

func readActionImpl(ctx context.Context, step *model.Step, actionDir string, actionPath string, readFile actionYamlReader, writeFile fileWriter) (*model.Action, error) {
	logger := common.Logger(ctx)
	allErrors := []error{}
	addError := func(fileName string, err error) {
		if err != nil {
			allErrors = append(allErrors, fmt.Errorf("failed to read '%s' from action '%s' with path '%s' of step: %w", fileName, step.String(), actionPath, err))
		} else {
			// One successful read, clear error state
			allErrors = nil
		}
	}
	reader, closer, err := readFile("action.yml")
	addError("action.yml", err)
	if os.IsNotExist(err) {
		reader, closer, err = readFile("action.yaml")
		addError("action.yaml", err)
		if os.IsNotExist(err) {
			_, closer, err := readFile("Dockerfile")
			addError("Dockerfile", err)
			if err == nil {
				closer.Close()
				action := &model.Action{
					Name: "(Synthetic)",
					Runs: model.ActionRuns{

View on GitHub (pinned to 4f41128141)