bmad-code-org/BMAD-METHOD · error · Error

Invalid action: ${options.action}. Valid actions: ${validAct

Error message

Invalid action: ${options.action}. Valid actions: ${validActions.join(', ')}

What it means

Thrown when --action <value> is passed but the value isn't in the dynamically-built choices list. Choices depend on install state: 'update' is always present for an existing install; 'quick-update' only appears when an existing install is detected. The valid set is printed in the message.

Source

Thrown at tools/installer/ui.js:293

      // Build menu choices dynamically
      const choices = [];

      // Always show Quick Update first (allows refreshing installation even on same version)
      if (existingInstall.installed) {
        choices.push({
          name: 'Quick Update',
          value: 'quick-update',
        });
      }

      // Common actions
      choices.push({ name: 'Modify BMAD Installation', value: 'update' });

      // Check if action is provided via command-line
      if (options.action) {
        const validActions = choices.map((c) => c.value);
        if (!validActions.includes(options.action)) {
          throw new Error(`Invalid action: ${options.action}. Valid actions: ${validActions.join(', ')}`);
        }
        actionType = options.action;
        await prompts.log.info(`Using action from command-line: ${actionType}`);
      } else if (options.yes) {
        // Default to quick-update if available, unless flags that require the
        // full update path are present (e.g. --custom-source which re-clones
        // modules at a new version — quick-update skips that entirely).
        if (choices.length === 0) {
          throw new Error('No valid actions available for this installation');
        }
        const hasQuickUpdate = choices.some((c) => c.value === 'quick-update');
        const needsFullUpdate = !!options.customSource;
        actionType = hasQuickUpdate && !needsFullUpdate ? 'quick-update' : (choices.find((c) => c.value === 'update') || choices[0]).value;
        await prompts.log.info(`Non-interactive mode (--yes): defaulting to ${actionType}`);
      } else {
        actionType = await prompts.select({
          message: 'How would you like to proceed?',
          choices: choices,

View on GitHub (pinned to b70486b9bd)

Solutions

  1. Use one of the actions printed in the error message (typically 'update' or 'quick-update').
  2. For a fresh install, omit --action — it only gates the existing-install menu.
  3. Ensure an existing BMAD install is present if you want quick-update.

Example fix

# before
#   --action install                       # not a valid action
#   --action quick-update                  # no existing install present
#
# after
#   --action update                        # valid for existing installs
#   (fresh install: drop --action entirely)
Defensive patterns

Strategy: validation

Validate before calling

const VALID = new Set(['update', 'quick-update']);
if (options.action && !VALID.has(options.action)) {
  console.error(`--action must be one of: ${[...VALID].join(', ')}. Omit for fresh installs.`);
  process.exit(1);
}

Type guard

function isValidAction(a, hasExistingInstall) {
  if (a === 'update') return true;
  if (a === 'quick-update') return hasExistingInstall;
  return false;
}

Try / catch

try {
  await ui.run(options);
} catch (e) {
  if (/^Invalid action:/.test(e.message)) {
    // drop --action and let the menu (or --yes) choose
    delete options.action;
    await ui.run(options);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Passing --action install or --action foo; passing --action quick-update against a directory with no existing _bmad install (so quick-update isn't offered).

Common situations: Typo in the action name; using quick-update against a fresh directory; version skew between docs and installer; passing an action that only applies to existing installs.

Related errors


AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13). Data as JSON: /api/errors/053804b3477ca398. Report an issue: GitHub.