nektos/act · error

missing steps in composite action

Error message

missing steps in composite action

What it means

Thrown in the pre stage of a composite action step (pkg/runner/action.go). Before running, act lazily builds the composite RunContext via step.getCompositeRunContext(ctx) and then expects getCompositeSteps() to yield a populated steps struct with a non-nil pre executor. If steps is nil (run context construction failed silently, e.g. action metadata could not be read) or steps.pre is nil (the composite action's action.yml defines no 'pre' step is acceptable — pre is then simply skipped), the nil-steps case is reported as 'missing steps in composite action'.

Source

Thrown at pkg/runner/action.go:580

			return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx)

		case x.IsDocker():
			if remoteAction == nil {
				actionDir = ""
				actionPath = containerActionDir
			}
			return execAsDocker(ctx, step, actionName, actionDir, actionPath, remoteAction == nil, "pre-entrypoint")

		case x.IsComposite():
			if step.getCompositeSteps() == nil {
				step.getCompositeRunContext(ctx)
			}

			if steps := step.getCompositeSteps(); steps != nil && steps.pre != nil {
				return steps.pre(ctx)
			}
			return fmt.Errorf("missing steps in composite action")

		default:
			return nil
		}
	}
}

func shouldRunPostStep(step actionStep) common.Conditional {
	return func(ctx context.Context) bool {
		log := common.Logger(ctx)
		stepResults := step.getRunContext().getStepsContext()
		stepResult := stepResults[step.getStepModel().ID]

		if stepResult == nil {
			log.WithField("stepResult", model.StepStatusSkipped).Debugf("skipping post step for '%s'; step was not executed", step.getStepModel())
			return false
		}

View on GitHub (pinned to 4f41128141)

Solutions

  1. Check the referenced action's action.yml exists and has 'runs: using: composite' with a non-empty 'runs.steps' list.
  2. For local actions, verify the 'uses:' path points at the directory containing action.yml (relative to the repo root, e.g. uses: ./.github/actions/my-action).
  3. For remote actions, verify the ref exists and the repo root actually contains action.yml; clear the action cache (~/.cache/act) in case of a corrupt clone.
  4. Validate the YAML parses (e.g. 'python -c "import yaml,sys;yaml.safe_load(open('action.yml'))"' or yamllint) — a YAML syntax error can leave steps unset.

Example fix

# before (action.yml)
runs:
  using: composite
# no steps key

# after
runs:
  using: composite
  steps:
    - run: echo hello
      shell: bash
Defensive patterns

Strategy: validation

Validate before calling

# before running act, assert the composite action metadata exists and has steps
ACTION_DIR=.github/actions/my-action
[ -f "$ACTION_DIR/action.yml" ] || { echo "missing $ACTION_DIR/action.yml"; exit 1; }
grep -q 'using: composite' "$ACTION_DIR/action.yml" && grep -qE '^\s+steps:' "$ACTION_DIR/action.yml"

Prevention

When it happens

Trigger: A 'uses: local/remote-composite-action' step whose action.yml is missing, malformed, unreadable, or contains no 'runs.steps' section; step.getCompositeRunContext succeeds but populate-step recursion (which calls newCompositeRunContext and builds steps) leaves getCompositeSteps() nil.

Common situations: Composite action metadata (action.yml/action.yaml) not committed, wrong path for a local action, remote composite action cloned to an empty dir, or an action.yml whose 'runs' block uses 'using: composite' but omits 'steps'.

Related errors


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