stablyai/orca · error · EmulatorError

emulator_device_not_found

emulator_device_not_found

Error message

"${deviceOrName}" is not a running device or a known AVD.

What it means

Thrown by bootAndroidDevice when the requested deviceOrName is neither a currently running adb serial nor an entry in `emulator -list-avds`. The check exists specifically so a stale/offline serial cannot launch an invalid `-avd` invocation and waste the entire boot timeout. It is an early-fail guard executed before any emulator process is spawned.

Source

Thrown at src/main/emulator/android/android-avd-boot.ts:36

export async function bootAndroidDevice(
  runner: AndroidCommandRunner,
  sdk: AndroidSdkPaths,
  deviceOrName: string,
  options: AndroidBootOptions
): Promise<string> {
  const running = await listRunningAdbDevices(runner, sdk)
  if (running.some((device) => device.serial === deviceOrName)) {
    return deviceOrName
  }
  const existing = await findRunningAvdSerial(runner, sdk, deviceOrName, running)
  if (existing) {
    return existing
  }
  // Validate the target is a real AVD before spawning, so a stale/offline serial
  // doesn't launch an invalid `-avd` and burn the full boot timeout.
  const avds = parseAvdList((await runner(sdk.emulator, listAvdsArgs)).stdout)
  if (!avds.includes(deviceOrName)) {
    throw new EmulatorError(
      'emulator_device_not_found',
      `"${deviceOrName}" is not a running device or a known AVD.`
    )
  }
  const known = new Set(running.map((device) => device.serial))
  launchAvd(sdk.emulator, deviceOrName)
  return waitForNewBootedSerial(runner, sdk, deviceOrName, known, options)
}

// Launches the emulator with spawn (NOT the command runner: execFile would kill
// the long-running, verbose emulator at its timeout / stdout maxBuffer). It is
// NOT detached: DETACHED_PROCESS gives the console-subsystem emulator no console,
// so it (and its qemu/netsim children) pop their own visible one. windowsHide
// gives it a hidden console instead; unref lets the app exit without waiting, and
// managed emulators are shut down on quit anyway. -no-window keeps it headless.
function launchAvd(emulatorPath: string, avdName: string): void {
  const child = spawn(emulatorPath, [...bootAvdArgs(avdName), '-no-window'], {
    stdio: 'ignore',

View on GitHub (pinned to 1136503c6a)

Solutions

  1. List valid targets first: run `emulator -list-avds` and `adb devices`, then pass an exact AVD name or running serial.
  2. If you intended a serial, boot the corresponding AVD first or ensure the emulator process is running.
  3. Verify ANDROID_HOME/ANDROID_AVD_HOME point at the directory holding the AVD ini files.
  4. Recreate the AVD with avdmanager if it was deleted.

Example fix

// before: passing a guessed name
await bootAndroidDevice(runner, sdk, 'Pixel7', opts) // not a real AVD
// after: discover then boot
const avds = parseAvdList((await runner(sdk.emulator, listAvdsArgs)).stdout)
const name = avds.find(a => a.startsWith('Pixel'))
if (!name) throw new Error(`no matching AVD; available: ${avds.join(', ')}`)
await bootAndroidDevice(runner, sdk, name, opts)
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the target exists as an AVD before invoking boot.
import { listAvdsArgs, parseAvdList } from './avd-manager'
import { listRunningAdbDevices } from './android-device-inventory'
async function resolveBootTarget(runner, sdk, name: string): Promise<string | null> {
  const running = await listRunningAdbDevices(runner, sdk)
  if (running.some(d => d.serial === name)) return name
  const avds = parseAvdList((await runner(sdk.emulator, listAvdsArgs)).stdout)
  return avds.includes(name) ? name : null
}

Type guard

import { EmulatorError } from '../emulator-errors'
function isDeviceNotFound(e: unknown): e is EmulatorError {
  return e instanceof EmulatorError && e.code === 'emulator_device_not_found'
}

Try / catch

try {
  await bootAndroidDevice(runner, sdk, target, opts)
} catch (e) {
  if (e instanceof EmulatorError && e.code === 'emulator_device_not_found') {
    const avds = parseAvdList((await runner(sdk.emulator, listAvdsArgs)).stdout)
    throw new Error(`Unknown target '${target}'. Available AVDs: ${avds.join(', ')}`)
  }
  throw e
}

Prevention

When it happens

Trigger: bootAndroidDevice(runner, sdk, deviceOrName, options) where deviceOrName is not in listRunningAdbDevices serials, not resolvable via findRunningAvdSerial, AND not present in parseAvdList of the emulator's AVD list. Common form: typo'd AVD name, a serial that belonged to a now-disconnected device, or an AVD that was deleted via avdmanager.

Common situations: User passes a device nickname or partial name that doesn't match the AVD's registered name; the AVD was created under a different ANDROID_AVD_HOME; emulator binary missing so list-avds returns empty; CI cache wiped ~/.android/avd; referencing an emulator-5554 serial after the emulator was killed.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/8925c55f863837d4. Report an issue: GitHub.