{"record":{"id":"72a2b9a166ca7bdf","repo":"moeru-ai/airi","slug":"the-first-cap-run-argument-must-be-ios-or-and-72a2b9","errorCode":null,"errorMessage":"The first `cap run` argument must be `ios` or `android`.","messagePattern":"The first `cap run` argument must be `ios` or `android`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cap-vite/src/vite-plugin.ts","lineNumber":107,"sourceCode":"      onRestart()\n    }\n  }\n\n  process.stdin.on('keypress', onKeyPress)\n\n  return () => {\n    process.stdin.off('keypress', onKeyPress)\n\n    if (shouldRestoreRawMode) {\n      process.stdin.setRawMode(false)\n    }\n  }\n}\n\nexport function capVitePlugin(options: CapVitePluginOptions): Plugin {\n  const platform = parseCapacitorPlatform(options.capArgs[0])\n  if (!platform) {\n    throw new Error('The first `cap run` argument must be `ios` or `android`.')\n  }\n  const resolvedPlatform: CapacitorPlatform = platform\n\n  return {\n    apply: 'serve',\n    name: 'cap-vite:run-capacitor',\n    async configureServer(server) {\n      const resolvedCapArgs = await resolveCapRunArgs(options.capArgs)\n      const cwd = resolve(server.config.root)\n      const platformRoot = resolve(cwd, resolvedPlatform)\n      const debounceMs = 300\n      const logger = server.config.logger\n\n      let currentCapProcess: Result | undefined\n      let restartTask: Promise<void> | undefined\n      let queuedRestartReason: string | undefined\n      let disposeShortcut: (() => void) | undefined\n      let shuttingDown = false","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/cap-vite/src/vite-plugin.ts#L89-L125","documentation":"Thrown by capVitePlugin() when options.capArgs[0] is not 'ios' or 'android'. Identical guard to runCapVite but inside the Vite plugin factory, which runs in the wrapper-config Vite process where capArgs arrive via the CAP_VITE_CAP_ARGS_JSON env var.","triggerScenarios":"The wrapper Vite config parses CAP_VITE_CAP_ARGS_JSON into an array whose first element is not 'ios'/'android'; the env var was set manually with a wrong first token; capArgs is empty because the env var was unset (parseCapArgs returns [], so capArgs[0] is undefined -> parseCapacitorPlatform returns null).","commonSituations":"Running the wrapper config directly (vite --config <wrapper>) without the env var that runCapVite normally injects; a test harness that loads vite-wrapper-config.ts with a malformed CAP_VITE_CAP_ARGS_JSON; a stale env var from a previous different-platform run.","solutions":["Do not invoke the wrapper config directly; go through runCapVite() which sets CAP_VITE_CAP_ARGS_JSON correctly.","If you must set it manually, ensure CAP_VITE_CAP_ARGS_JSON is a JSON array like [\"ios\"] or [\"android\",\"--target\",\"<id>\"].","Clear stale CAP_VITE_CAP_ARGS_JSON from the shell environment before a platform switch."],"exampleFix":"# before\nCAP_VITE_CAP_ARGS_JSON='[\"--target\",\"abc\"]' vite --config wrapper\n# after\nCAP_VITE_CAP_ARGS_JSON='[\"ios\",\"--target\",\"abc\"]' vite --config wrapper","handlingStrategy":"validation","validationCode":"function assertCapArgsEnv(raw: string | undefined): asserts raw is string | undefined {\n  if (raw !== undefined) {\n    const parsed = JSON.parse(raw)\n    if (!Array.isArray(parsed) || !parsed.every(v => typeof v === 'string') || !['ios','android'].includes(parsed[0])) {\n      throw new Error('CAP_VITE_CAP_ARGS_JSON must be a string[] starting with ios|android')\n    }\n  }\n}","typeGuard":"function isValidCapArgsEnv(raw: string | undefined): boolean {\n  if (!raw) return true\n  try {\n    const p = JSON.parse(raw)\n    return Array.isArray(p) && p.every(v => typeof v === 'string') && (p[0] === 'ios' || p[0] === 'android')\n  } catch { return false }\n}","tryCatchPattern":"try {\n  capVitePlugin({ capArgs })\n} catch (error) {\n  if (error instanceof Error && error.message.includes('ios` or `android')) {\n    throw new Error('Plugin capArgs[0] must be ios|android. Check CAP_VITE_CAP_ARGS_JSON.')\n  }\n  throw error\n}","preventionTips":["Always go through runCapVite() so the env var is set correctly.","Never reuse CAP_VITE_CAP_ARGS_JSON across platform switches without clearing it.","Unit-test the wrapper config with a known-good env value."],"tags":["capacitor","vite-plugin","environment","argument-validation"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}