stablyai/orca · error · EmulatorError

emulator_no_active

emulator_no_active

Error message

iOS simulator ${udid} is not active for this worktree (active: ${session.deviceUdid}); attach the requested simulator first.

What it means

accessibilityTree() resolved a udid that differs from the device the worktree currently has attached. It is a guard so a read never silently targets a simulator the user did not select for that worktree.

Source

Thrown at src/main/emulator/emulator-bridge.ts:217

    const { backend, device } = await this.resolveTarget(opts)
    return backend.exec(device, command)
  }

  async accessibilityTree(opts?: EmulatorTargetOpts): Promise<unknown> {
    return this.runCapability('accessibilityTree', opts, async (backend, device) => {
      if (backend.kind !== 'ios') {
        return backend.accessibilityTree!(device)
      }
      const udid = await backend.resolveDeviceId(device)
      const worktreeId = opts?.worktreeId
      // Fall back to the udid-keyed session so an explicit --device read works
      // from a worktree with no active emulator (matching tap/type reachability);
      // sessions are stored once per udid, so both lookups hit the same state.
      const session =
        (worktreeId ? this.getActiveForWorktree(worktreeId) : null) ??
        this.sessionRegistry.getSession(udid)
      if (worktreeId && session && session.deviceUdid !== udid) {
        throw new EmulatorError(
          'emulator_no_active',
          `iOS simulator ${udid} is not active for this worktree (active: ${session.deviceUdid}); attach the requested simulator first.`
        )
      }
      // Heal sessions registered without an axUrl (parse-time derivation only
      // covers fresh --detach output) by deriving it from the mjpeg stream URL.
      const axUrl = session?.axUrl ?? deriveAxUrlFromStreamUrl(session?.streamUrl)
      return backend.accessibilityTree!(udid, axUrl)
    })
  }

  // Runs a capability-gated verb against the resolved target, rejecting backends
  // that do not advertise the capability (e.g. install/logcat on iOS).
  async runCapability<T>(
    capability: keyof EmulatorBackendCapabilities,
    opts: EmulatorTargetOpts | undefined,
    run: (backend: EmulatorBackend, deviceId: string) => Promise<T>
  ): Promise<T> {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Run `orca emulator attach <requested-udid>` for the worktree so the active session matches.
  2. Drop the explicit --device from the call so the worktree's already-active simulator is used.
  3. If the registry is stale, run `orca emulator kill` for the worktree and re-attach the correct device.

Example fix

// before
await bridge.accessibilityTree({ worktreeId, device: requestedUdid }) // active != requestedUdid

// after
await emulatorAttach({ worktreeId, device: requestedUdid })
await bridge.accessibilityTree({ worktreeId })
Defensive patterns

Strategy: validation

Validate before calling

const active = bridge.getActiveForWorktree(worktreeId)
if (active && active.deviceUdid !== requestedUdid) { /* attach requestedUdid first or drop --device */ }

Type guard

function isEmulatorError(e: unknown, code = 'emulator_no_active'): e is import('./emulator-errors').EmulatorError {
  return e instanceof Error && (e as any).code === code && e.name === 'EmulatorError'
}

Try / catch

try { await bridge.accessibilityTree({ worktreeId, device: udid }) }
catch (e) { if (isEmulatorError(e, 'emulator_no_active')) { await emulatorAttach({ worktreeId, device: udid }) } else throw e }

Prevention

When it happens

Trigger: accessibilityTree({ worktreeId }) is called; getActiveForWorktree(worktreeId) returns a session whose deviceUdid !== the resolved udid (emulator-bridge.ts:216-220). The explicit --device resolves to one simulator while the worktree is bound to another.

Common situations: User switched the active emulator in another worktree; a stale --device value was passed; the session registry was repointed to a newly-attached device while old commands still reference the prior udid.

Related errors


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