nektos/act · error

The runs.using key must be one of: %v, got %s

Error message

The runs.using key must be one of: %v, got %s

What it means

Execution-time counterpart of the model validation: runAction switches on action.Runs.Using and falls into default when the value is not docker/node12/node16/node20/node24/composite. Because UnmarshalYAML already rejects bad values, hitting this usually means the Action struct was constructed without parsing metadata at all (zero-value Using), e.g. the Dockerfile-only fallback path where no action.yml exists.

Source

Thrown at pkg/runner/action.go:202

			logger.Debugf("executing remote job container: %s", containerArgs)

			rc.ApplyExtraPath(ctx, step.getEnv())

			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, "entrypoint")
		case x.IsComposite():
			if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil {
				return err
			}

			return execAsComposite(step)(ctx)
		default:
			return fmt.Errorf("The runs.using key must be one of: %v, got %s", []string{
				model.ActionRunsUsingDocker,
				model.ActionRunsUsingNode12,
				model.ActionRunsUsingNode16,
				model.ActionRunsUsingNode20,
				model.ActionRunsUsingNode24,
				model.ActionRunsUsingComposite,
			}, action.Runs.Using)
		}
	}
}

func setupActionEnv(ctx context.Context, step actionStep, _ *remoteAction) error {
	rc := step.getRunContext()

	// A few fields in the environment (e.g. GITHUB_ACTION_REPOSITORY)
	// are dependent on the action. That means we can complete the
	// setup only after resolving the whole action model and cloning
	// the action

View on GitHub (pinned to 4f41128141)

Solutions

  1. Add an action.yml to the action repo declaring `runs: { using: docker, image: Dockerfile }` so the Dockerfile path is explicit.
  2. If embedding act, always construct model.Action via ReadAction (YAML) rather than struct literals.
  3. Update act — mismatches between model constants and the runner switch are fixed in newer releases.

Example fix

# add action.yml next to Dockerfile
name: my-action
description: runs container
runs:
  using: docker
  image: Dockerfile
Defensive patterns

Strategy: validation

Validate before calling

func hasValidUsing(a *model.Action) bool {
    switch a.Runs.Using {
    case model.ActionRunsUsingDocker, model.ActionRunsUsingNode12, model.ActionRunsUsingNode16,
         model.ActionRunsUsingNode20, model.ActionRunsUsingNode24, model.ActionRunsUsingComposite:
        return true
    }
    return false
}

Try / catch

if err != nil && strings.Contains(err.Error(), "The runs.using key must be one of") {
    // the action was loaded without real metadata; add action.yml next to the Dockerfile and re-run
}

Prevention

When it happens

Trigger: An action directory contains only a Dockerfile (no action.yml/action.yaml): readActionImpl returns an Action built from defaults with an empty Runs.Using, which then fails this switch. Also reachable when embedding act and supplying a hand-built model.Action with an unrecognized Using value.

Common situations: Dockerfile-only actions that GitHub supports implicitly but act requires metadata for; programmatic users bypassing YAML parsing; new runtime values added to the model but not to this switch in the runner.

Related errors


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