{"record":{"id":"d47560f04599bffc","repo":"nektos/act","slug":"invalid-run-uses-syntax-for-job-s-step-v","errorCode":null,"errorMessage":"Invalid run/uses syntax for job:%s step:%+v","messagePattern":"Invalid run/uses syntax for job:(.+?) step:%\\+v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runner/step_factory.go","lineNumber":18,"sourceCode":"package runner\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/nektos/act/pkg/model\"\n)\n\ntype stepFactory interface {\n\tnewStep(step *model.Step, rc *RunContext) (step, error)\n}\n\ntype stepFactoryImpl struct{}\n\nfunc (sf *stepFactoryImpl) newStep(stepModel *model.Step, rc *RunContext) (step, error) {\n\tswitch stepModel.Type() {\n\tcase model.StepTypeInvalid:\n\t\treturn nil, fmt.Errorf(\"Invalid run/uses syntax for job:%s step:%+v\", rc.Run, stepModel)\n\tcase model.StepTypeRun:\n\t\treturn &stepRun{\n\t\t\tStep:       stepModel,\n\t\t\tRunContext: rc,\n\t\t}, nil\n\tcase model.StepTypeUsesActionLocal:\n\t\treturn &stepActionLocal{\n\t\t\tStep:       stepModel,\n\t\t\tRunContext: rc,\n\t\t\treadAction: readActionImpl,\n\t\t\trunAction:  runActionImpl,\n\t\t}, nil\n\tcase model.StepTypeUsesActionRemote:\n\t\treturn &stepActionRemote{\n\t\t\tStep:       stepModel,\n\t\t\tRunContext: rc,\n\t\t\treadAction: readActionImpl,\n\t\t\trunAction:  runActionImpl,","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/runner/step_factory.go#L1-L36","documentation":"The step factory could not classify the step: model.Step.Type() returned StepTypeInvalid, which happens when both `run:` and `uses:` are empty, or when both are set on the same step. The factory therefore has no step implementation to instantiate and returns this error naming the job and echoing the whole step model.","triggerScenarios":"A step block in the workflow has neither `run:` nor `uses:`, or declares both at once; often a side effect of YAML indentation putting keys at the wrong level so the step struct ends up empty.","commonSituations":"Copy-paste merging two step examples leaving both keys; YAML indentation that detaches run/uses from the step map (making them job-level or ignored); a step reduced to only `name:`/`with:` after editing; template placeholders never filled in.","solutions":["Give each step exactly one of `run:` or `uses:`.","Check indentation: keys of a step must align under the same '- ' item; a misplaced run: one level up yields an empty step.","Run actionlint on the workflow — it flags steps missing run/uses immediately."],"exampleFix":"# before\n- name: build\n  run: make build\n  uses: actions/setup-go@v5   # both set\n# after\n- name: build\n  uses: actions/setup-go@v5\n- name: build\n  run: make build","handlingStrategy":"validation","validationCode":"python3 - <<'EOF'\nimport yaml,sys\nfor f in __import__('glob').glob('.github/workflows/*.yml'):\n    wf=yaml.safe_load(open(f))\n    for j in wf.get('jobs',{}).values():\n        for s in j.get('steps',[]):\n            has_run=bool(s.get('run')); has_uses=bool(s.get('uses'))\n            if has_run == has_uses:  # both or neither\n                sys.exit(f\"{f}: step {s.get('name')} must have exactly one of run/uses\")\nEOF","typeGuard":"func stepWellFormed(s map[string]any) bool {\n  _, r := s[\"run\"]; _, u := s[\"uses\"]\n  return r != u // exactly one present\n}","tryCatchPattern":null,"preventionTips":["Exactly one of run or uses per step — never both, never neither.","Watch YAML indentation under '- name:'.","Run actionlint in CI; it detects structurally invalid steps."],"tags":["workflow-syntax","steps","validation","yaml"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}