stablyai/orca · error · EmulatorError
emulator_helper_failed
emulator_helper_failed
Error message
serve-sim AX request failed (${response.status}): ${detail}.${retry} What it means
requestServeSimAccessibilityTree received an HTTP response with a non-2xx status from the serve-sim /ax endpoint. For 503 the message appends a 'warming up, retry' hint because the accessibility service often is not ready immediately after boot.
Source
Thrown at src/main/emulator/serve-sim-accessibility-tree.ts:17
import { net } from 'electron'
import { EmulatorError } from './emulator-errors'
import { normalizeServeSimAxTree, type NormalizedAxNode } from './serve-sim-ax-normalization'
const AX_REQUEST_TIMEOUT_MS = 5_000
const MAX_ERROR_BODY_LENGTH = 512
export async function requestServeSimAccessibilityTree(axUrl: string): Promise<NormalizedAxNode[]> {
try {
const response = await net.fetch(axUrl, {
signal: AbortSignal.timeout(AX_REQUEST_TIMEOUT_MS)
})
const body = await response.text()
if (!response.ok) {
const detail = body.slice(0, MAX_ERROR_BODY_LENGTH) || response.statusText
const retry = response.status === 503 ? ' Accessibility may still be warming up; retry.' : ''
throw new EmulatorError(
'emulator_helper_failed',
`serve-sim AX request failed (${response.status}): ${detail}.${retry}`
)
}
let tree: unknown
try {
tree = JSON.parse(body)
} catch {
throw new EmulatorError('emulator_error', 'serve-sim AX returned invalid JSON.')
}
if (
!Array.isArray(tree) ||
tree.some((node) => typeof node !== 'object' || node === null || Array.isArray(node))
) {
throw new EmulatorError('emulator_error', 'serve-sim AX returned an invalid tree.')
}
// serve-sim reports frames in absolute pixels; normalize to 0..1 so theView on GitHub (pinned to 1136503c6a)
Solutions
- Retry accessibilityTree after a short delay (the 503 case is explicitly retryable).
- Ensure `orca emulator attach` completed and the simulator finished booting before the first AX read.
- Check serve-sim logs for the status detail embedded in the error message.
Example fix
// before
await requestServeSimAccessibilityTree(axUrl) // 503 right after boot
// after
await waitForSimulatorBooted(udid)
await retry(() => requestServeSimAccessibilityTree(axUrl), { tries: 3, delayMs: 500 }) Defensive patterns
Strategy: retry
Validate before calling
const probe = await fetch(axUrl, { signal: AbortSignal.timeout(1000) }).catch(() => null)
if (probe && probe.status === 503) { /* AX still warming up; wait then call */ } Type guard
function isEmulatorError(e: unknown, code = 'emulator_helper_failed'): e is import('./emulator-errors').EmulatorError {
return e instanceof Error && (e as any).code === code && e.name === 'EmulatorError'
} Try / catch
try { return await requestServeSimAccessibilityTree(axUrl) }
catch (e) {
if (isEmulatorError(e) && /503|warming up/.test(e.message)) { await delay(500); return await requestServeSimAccessibilityTree(axUrl) }
throw e
} Prevention
- Wait for boot to settle before the first AX read.
- Treat 503 as retryable.
- Surface the embedded status/body detail when reporting the error.
When it happens
Trigger: net.fetch(axUrl) returns response.ok === false (serve-sim-accessibility-tree.ts:14-20). The first 512 bytes of the body (or statusText) become the detail; status 503 adds the retry suffix.
Common situations: Calling accessibilityTree right after attach (AX not yet warm); serve-sim internal error; simulator still mid-boot; the /ax endpoint temporarily overloaded.
Related errors
- emulator_error
- accessibility_error
- emulator_no_active
- emulator_helper_failed
- Translation request failed with status ${response.status}
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/7148b0ef1b1dcafa.
Report an issue: GitHub.