{"record":{"id":"053804b3477ca398","repo":"bmad-code-org/BMAD-METHOD","slug":"invalid-action-options-action-valid-actions","errorCode":null,"errorMessage":"Invalid action: ${options.action}. Valid actions: ${validActions.join(', ')}","messagePattern":"Invalid action: (.+?)\\. Valid actions: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"tools/installer/ui.js","lineNumber":293,"sourceCode":"      // Build menu choices dynamically\n      const choices = [];\n\n      // Always show Quick Update first (allows refreshing installation even on same version)\n      if (existingInstall.installed) {\n        choices.push({\n          name: 'Quick Update',\n          value: 'quick-update',\n        });\n      }\n\n      // Common actions\n      choices.push({ name: 'Modify BMAD Installation', value: 'update' });\n\n      // Check if action is provided via command-line\n      if (options.action) {\n        const validActions = choices.map((c) => c.value);\n        if (!validActions.includes(options.action)) {\n          throw new Error(`Invalid action: ${options.action}. Valid actions: ${validActions.join(', ')}`);\n        }\n        actionType = options.action;\n        await prompts.log.info(`Using action from command-line: ${actionType}`);\n      } else if (options.yes) {\n        // Default to quick-update if available, unless flags that require the\n        // full update path are present (e.g. --custom-source which re-clones\n        // modules at a new version — quick-update skips that entirely).\n        if (choices.length === 0) {\n          throw new Error('No valid actions available for this installation');\n        }\n        const hasQuickUpdate = choices.some((c) => c.value === 'quick-update');\n        const needsFullUpdate = !!options.customSource;\n        actionType = hasQuickUpdate && !needsFullUpdate ? 'quick-update' : (choices.find((c) => c.value === 'update') || choices[0]).value;\n        await prompts.log.info(`Non-interactive mode (--yes): defaulting to ${actionType}`);\n      } else {\n        actionType = await prompts.select({\n          message: 'How would you like to proceed?',\n          choices: choices,","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/bmad-code-org/BMAD-METHOD/blob/b70486b9bdcb0a404d329e2a763b57964e7f1360/tools/installer/ui.js#L275-L311","documentation":"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.","triggerScenarios":"Passing --action install or --action foo; passing --action quick-update against a directory with no existing _bmad install (so quick-update isn't offered).","commonSituations":"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.","solutions":["Use one of the actions printed in the error message (typically 'update' or 'quick-update').","For a fresh install, omit --action — it only gates the existing-install menu.","Ensure an existing BMAD install is present if you want quick-update."],"exampleFix":"# before\n#   --action install                       # not a valid action\n#   --action quick-update                  # no existing install present\n#\n# after\n#   --action update                        # valid for existing installs\n#   (fresh install: drop --action entirely)","handlingStrategy":"validation","validationCode":"const VALID = new Set(['update', 'quick-update']);\nif (options.action && !VALID.has(options.action)) {\n  console.error(`--action must be one of: ${[...VALID].join(', ')}. Omit for fresh installs.`);\n  process.exit(1);\n}","typeGuard":"function isValidAction(a, hasExistingInstall) {\n  if (a === 'update') return true;\n  if (a === 'quick-update') return hasExistingInstall;\n  return false;\n}","tryCatchPattern":"try {\n  await ui.run(options);\n} catch (e) {\n  if (/^Invalid action:/.test(e.message)) {\n    // drop --action and let the menu (or --yes) choose\n    delete options.action;\n    await ui.run(options);\n  } else { throw e; }\n}","preventionTips":["Only pass --action for existing installs; omit it for fresh installs.","Cross-check the action name against the error message's valid list before retrying."],"tags":["cli","installer","action-selection"],"backgroundTag":null,"analyzedSha":"b70486b9bdcb0a404d329e2a763b57964e7f1360","analyzedAt":"2026-08-13T01:21:12.247Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}