moeru-ai/airi · error
No ${platform} devices or simulators found. Connect a device
Error message
No ${platform} devices or simulators found. Connect a device, start a simulator or emulator, or pass --target explicitly. What it means
Thrown by resolveCapRunArgs() when no explicit --target was supplied, no device id is in CAPACITOR_DEVICE_ID_IOS/ANDROID, and listTargets(platform) returned an empty or id-less list. It is the final fallback before cap-vite injects a --target value for the Capacitor run.
Source
Thrown at packages/cap-vite/src/native.ts:155
let target: string | undefined
if (platform === 'ios') {
target = env.CAPACITOR_DEVICE_ID_IOS
}
else if (platform === 'android') {
target = env.CAPACITOR_DEVICE_ID_ANDROID
}
if (!target) {
if (!platform) {
return capArgs
}
const targets = await listTargets(platform)
target = targets.find(device => device.id)?.id
}
if (!target) {
throw new Error(`No ${platform} devices or simulators found. Connect a device, start a simulator or emulator, or pass --target explicitly.`)
}
return [platformArg, '--target', target, ...rest]
}
export function pickServerUrl(server: Pick<ViteDevServer, 'resolvedUrls'>): URL {
const url = server.resolvedUrls?.network?.[0] ?? server.resolvedUrls?.local?.[0]
if (!url) {
throw new Error('Vite did not expose a reachable dev server URL.')
}
return new URL(url)
}
export function shouldRestartForNativeChange(file: string, platform: CapacitorPlatform, cwd: string): boolean {
const absoluteFile = resolve(cwd, file)
const platformRoot = resolve(cwd, platform)View on GitHub (pinned to 27111382b4)
Solutions
- Start an iOS Simulator (open -a Simulator) or an Android emulator (emulator -avd <name>) and retry.
- Connect and trust a physical device over USB/Wi-Fi debugging.
- Pass an explicit target: runCapVite(viteArgs, ['ios', '--target', '<id>']).
- Set CAPACITOR_DEVICE_ID_IOS or CAPACITOR_DEVICE_ID_ANDROID to a known device id to skip discovery.
Example fix
// before await runCapVite(viteArgs, ['ios']) // after await runCapVite(viteArgs, ['ios', '--target', '00008110-XXXX'])
Defensive patterns
Strategy: try-catch
Validate before calling
// Check device availability before relying on auto-discovery
import { x } from 'tinyexec'
async function hasAnyTarget(platform: 'ios' | 'android'): Promise<boolean> {
try {
const out = await x('cap', ['run', platform, '--list', '--json'])
const list = JSON.parse(out.stdout) as { id?: string }[]
return list.some(t => typeof t.id === 'string')
} catch { return false }
} Try / catch
try {
await runCapVite(viteArgs, ['ios'])
} catch (error) {
if (error instanceof Error && /No .* devices or simulators found/.test(error.message)) {
console.error('Start an iOS Simulator or pass --target <id>.')
process.exit(1)
}
throw error
} Prevention
- Boot a simulator/emulator before invoking cap-vite.
- Set CAPACITOR_DEVICE_ID_IOS/ANDROID in a .env for your dev machine.
- In CI, launch the emulator as a setup step and wait for boot.
When it happens
Trigger: Calling runCapVite or capVitePlugin on a machine with no connected device, no running iOS Simulator, and no running Android emulator; listTargets returns [] because no target has a string id.
Common situations: First run on a fresh dev machine with no simulator booted; CI without a booted emulator; the platform tooling (Xcode simulators / AVD) is installed but nothing is launched; USB device not trusted/paired.
Related errors
- AIRI host websocket bridge is unavailable
- cap-vite [vite args...] -- <ios|android> [cap run args...]
- The first `cap run` argument must be `ios` or `android`.
- Expected `cap run --list --json` to return a JSON array.
- Vite did not expose a reachable dev server URL.
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/cc2e9a346c7c9715.
Report an issue: GitHub.