stablyai/orca · error · EmulatorError

emulator_error

emulator_error

Error message

Could not read screen size for ${serial}.

What it means

Thrown by AndroidEmulatorBackend.getScreenSize when `adb shell wm size` succeeds (no adb error) but parseWmSize cannot extract a usable size from the output. The size is cached per serial after a successful parse, so this only fires on the first attempt for a given device. It indicates the wm size output format was unparseable.

Source

Thrown at src/main/emulator/backends/android-emulator-backend.ts:323

  // Boots an AVD (by name) when not running and waits for boot; returns the serial.
  async ensureBooted(deviceOrName: string): Promise<string> {
    return bootAndroidDevice(this.runner, this.requireSdk(), deviceOrName, {
      bootTimeoutMs: this.bootTimeoutMs,
      pollIntervalMs: this.pollIntervalMs,
      sleep: this.sleep
    })
  }

  private async getScreenSize(serial: string): Promise<DeviceScreenSize> {
    const cached = this.screenSizes.get(serial)
    if (cached) {
      return cached
    }
    const sdk = this.requireSdk()
    const result = await this.runner(sdk.adb, wmSizeArgs(serial))
    const size = parseWmSize(result.stdout)
    if (!size) {
      throw new EmulatorError('emulator_error', `Could not read screen size for ${serial}.`)
    }
    this.screenSizes.set(serial, size)
    return size
  }

  private requireSdk(): AndroidSdkPaths {
    return this.sdkState.require()
  }
}

function defaultSleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms))
}

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Run `adb -s <serial> shell wm size` manually and compare its output to what parseWmSize expects.
  2. Retry after a short delay if the display service may not be ready (common right after boot).
  3. Ensure the emulator/AVD has a display configured (headless AVDs without a skin can return no size).
  4. If the format legitimately differs on your API level, extend parseWmSize to handle it.

Example fix

// before: calling getScreenSize immediately after boot
const size = await backend.getScreenSize(serial)
// after: let the display settle, then read
await sleep(2000)
const size = await backend.getScreenSize(serial)
Defensive patterns

Strategy: retry

Validate before calling

// Sanity-check wm size output before relying on it.
function wmSizeLooksValid(stdout: string): boolean {
  return /Physical size:\s*\d+x\d+/i.test(stdout)
}

Type guard

import { EmulatorError } from '../emulator-errors'
function isScreenSizeError(e: unknown): e is EmulatorError {
  return e instanceof EmulatorError && /read screen size/i.test(e.message)
}

Try / catch

for (let i = 0; i < 3; i++) {
  try { return await backend.getScreenSize(serial) }
  catch (e) {
    if (isScreenSizeError(e) && i < 2) { await sleep(1000); continue }
    throw e
  }
}

Prevention

When it happens

Trigger: getScreenSize(serial) on a serial with no cached entry; runner(sdk.adb, wmSizeArgs(serial)) returns code 0 but parseWmSize(result.stdout) yields null. Subsequent calls hit the cache and do not re-throw.

Common situations: An API level where `wm size` output differs from the expected 'Physical size: WxH' format; a device whose display service is not ready yet (wm returns empty/garbled); a headless emulator with no display configured; a resolution parsing edge case (unusual density/override lines).

Related errors


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