moeru-ai/airi · error · Error
The first `cap run` argument must be `ios` or `android`.
Error message
The first `cap run` argument must be `ios` or `android`.
What it means
The cap-vite Vite plugin validates options.capArgs[0] at construction time with parseCapacitorPlatform and throws when it is not 'ios' or 'android'. Normally capArgs arrive already validated from the CLI/env pipeline (CAP_VITE_CAP_ARGS_JSON), so hitting this means the plugin was instantiated directly with malformed args.
Solutions
- Pass the platform as the first element: capVitePlugin({ capArgs: ['ios', '--target', 'iPhone 16 Pro'] })
- Prefer deriving capArgs from parseCapViteCliArgs(argv) instead of assembling them by hand
- If driving the wrapper config via env, set CAP_VITE_CAP_ARGS_JSON as a JSON array starting with the platform
Example fix
// before
capVitePlugin({ capArgs: ['--target', 'emulator-5554'] }) // Error: The first `cap run` argument must be `ios` or `android`.
// after
capVitePlugin({ capArgs: ['android', '--target', 'emulator-5554'] }) Defensive patterns
Strategy: validation
Validate before calling
const platform = options.capArgs[0]
if (platform !== 'ios' && platform !== 'android')
throw new Error(`capVitePlugin requires capArgs[0] to be ios|android, got: ${platform}`)
return capVitePlugin({ ...options }) Type guard
function isCapacitorPlatform(v: string | undefined): v is 'ios' | 'android' {
return v === 'ios' || v === 'android'
} Prevention
- Derive capArgs from parseCapViteCliArgs instead of constructing them ad hoc
- Prefer running through the cap-vite CLI so validation happens upstream
- Cover plugin construction with a unit test asserting the platform precondition
When it happens
Trigger: Calling capVitePlugin({ capArgs: [] }) (empty array), capVitePlugin({ capArgs: ['--target', 'x'] }) (flag first), or passing a platform string with wrong case; the plugin factory throws before Vite even starts.
Common situations: Using capVitePlugin in a custom vite.config.ts instead of going through `cap-vite -- <platform>`; hand-building capArgs from user input without putting the platform first; tests constructing the plugin with placeholder args.
Understand the failure class
Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.
Related errors
- The first `cap run` argument must be `ios` or `android`.
- CAP_VITE_CAP_ARGS_JSON must be a JSON string array.
- cap-vite [vite args...] -- <ios|android> [cap run args...]
- Missing value for ` `.
- Beat Sync is not available in Stage Pocket
AI-assisted analysis of moeru-ai/airi@0616eabd5b (2026-08-18).
Data as JSON: /api/errors/72a2b9a166ca7bdf.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cap-vite/src/vite-plugin.ts:24
import process from 'node:process'
import { resolve } from 'node:path'
import * as readline from 'node:readline'
import { x } from 'tinyexec'
import { parseCapacitorPlatform, pickServerUrl, resolveCapRunArgs, shouldRestartForNativeChange } from './native'
import { errorMessageFromValue } from './utils/error-message'
export interface CapVitePluginOptions {
capArgs: string[]
}
export function capVitePlugin(options: CapVitePluginOptions): Plugin {
const platform = parseCapacitorPlatform(options.capArgs[0])
if (!platform) {
throw new Error('The first `cap run` argument must be `ios` or `android`.')
}
const resolvedPlatform: CapacitorPlatform = platform
return {
apply: 'serve',
async configureServer(server) {
const resolvedCapArgs = await resolveCapRunArgs(options.capArgs)
const cwd = resolve(server.config.root)
const platformRoot = resolve(cwd, resolvedPlatform)
const debounceMs = 300
const logger = server.config.logger
let currentCapProcess: Result | undefined
let restartTask: Promise<void> | undefined
let queuedRestartReason: string | undefined
let disposeShortcut: (() => void) | undefined
let shuttingDown = false
let restartTimer: NodeJS.Timeout | undefinedView on GitHub (pinned to 0616eabd5b)