{"record":{"id":"f833909d7d3b2fdb","repo":"stablyai/orca","slug":"emulator-error-f83390","errorCode":"emulator_error","errorMessage":"adb install failed: ${(result.stderr || result.stdout).trim() || 'unknown error'}","messagePattern":"adb install failed: (.+?)","errorType":"exception","errorClass":"EmulatorError","httpStatus":null,"severity":"error","filePath":"src/main/emulator/android/android-capability-operations.ts","lineNumber":25,"sourceCode":"import { logcatArgs, parseLogcatLine, type LogcatEntry } from './android-logcat'\nimport { parseUiAutomatorXml, type AndroidAxNode } from './uiautomator-tree'\n\n// Impure capability operations: compose the pure arg-builders/parsers with the\n// command runner. The backend exposes thin delegations to these.\n\nconst UIAUTOMATOR_DUMP_PATH = '/sdcard/window_dump.xml'\n\nexport async function installAndroidApk(\n  runner: AndroidCommandRunner,\n  sdk: AndroidSdkPaths,\n  serial: string,\n  apkPath: string,\n  options?: { reinstall?: boolean }\n): Promise<void> {\n  const result = await runner(sdk.adb, installApkArgs(serial, apkPath, options))\n  // adb install can exit 0 while printing \"Failure [...]\" to stdout.\n  if (result.code !== 0 || /Failure|Error/i.test(`${result.stdout}${result.stderr}`)) {\n    throw new EmulatorError(\n      'emulator_error',\n      `adb install failed: ${(result.stderr || result.stdout).trim() || 'unknown error'}`\n    )\n  }\n}\n\nexport async function launchAndroidApp(\n  runner: AndroidCommandRunner,\n  sdk: AndroidSdkPaths,\n  serial: string,\n  packageName: string,\n  activity?: string\n): Promise<void> {\n  ensureAdbOk(await runner(sdk.adb, launchAppArgs(serial, packageName, activity)), 'adb launch')\n}\n\nexport async function setAndroidPermission(\n  runner: AndroidCommandRunner,","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/emulator/android/android-capability-operations.ts#L7-L43","documentation":"Thrown by installAndroidApk when `adb install` either exits non-zero OR prints a 'Failure'/'Error' marker to stdout/stderr. The dual check is deliberate: adb install is known to exit 0 while reporting 'Failure [...]' on stdout, so a code-only check would let failed installs pass as successes. The message embeds the trimmed adb output for diagnosis.","triggerScenarios":"installAndroidApk(runner, sdk, serial, apkPath, options) where the install result has code !== 0, or where /Failure|Error/i matches the concatenation of stdout and stderr. Commonly triggered by an APK signed with an incompatible signature, an already-installed package with reinstall not set, an APK missing a required ABI, or insufficient storage.","commonSituations":"Reinstalling an APK signed differently without --reinstall (INSTALL_FAILED_UPDATE_INCOMPATIBLE / signatures do not match); INSTALL_FAILED_NO_MATCHING_ABI on a missing architecture; INSUFFICIENT_STORAGE on a full emulator; downgrade attempt (INSTALL_FAILED_VERSION_DOWNGRADE); an APK built for a different minSdk than the emulator's API level.","solutions":["Read the embedded Failure code in the message — adb's reason string (e.g. INSTALL_FAILED_UPDATE_INCOMPATIBLE) names the exact problem.","For signature mismatches, uninstall first: `adb -s <serial> uninstall <package>` then reinstall, or pass { reinstall: true } which maps to adb install -r.","For ABI mismatches, build a universal APK or include the emulator's ABI (x86_64 for standard emulators).","Free up emulator storage (`adb shell df /data`) and clear unused packages if INSUFFICIENT_STORAGE appears.","For downgrades, build a higher versionCode or use adb install -d (downgrade) explicitly."],"exampleFix":"// before: reinstall collides with prior signature\nawait installAndroidApk(runner, sdk, serial, apkPath)\n// after: permit replace of existing install\nawait installAndroidApk(runner, sdk, serial, apkPath, { reinstall: true })","handlingStrategy":"validation","validationCode":"// Pre-check signature/version compatibility before install.\nasync function canReinstall(runner, sdk, serial, pkg): Promise<boolean> {\n  const r = await runner(sdk.adb, ['-s', serial, 'shell', 'pm', 'path', pkg])\n  return r.code === 0 && r.stdout.includes('package:')\n}","typeGuard":"import { EmulatorError } from '../emulator-errors'\nfunction isInstallError(e: unknown): e is EmulatorError {\n  return e instanceof EmulatorError && e.code === 'emulator_error' && /install/i.test(e.message)\n}","tryCatchPattern":"try {\n  await installAndroidApk(runner, sdk, serial, apk, { reinstall: true })\n} catch (e) {\n  if (e instanceof EmulatorError && /UPDATE_INCOMPATIBLE/.test(e.message)) {\n    await runner(sdk.adb, ['-s', serial, 'uninstall', pkg])\n    await installAndroidApk(runner, sdk, serial, apk)\n    return\n  }\n  throw e\n}","preventionTips":["Pass { reinstall: true } when an existing install may be present.","Uninstall before installing if the signing key changed.","Build APKs with the emulator's ABI (x86_64) to avoid ABI failures."],"tags":["android","adb","apk-install","signature","emulator"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}