{"record":{"id":"e4fd292a18649c95","repo":"expo/expo","slug":"unable-to-launch-app-number-of-tries-exceeded","errorCode":null,"errorMessage":"Unable to launch app, number of tries exceeded","messagePattern":"Unable to launch app, number of tries exceeded","errorType":"exception","errorClass":"CommandError","httpStatus":null,"severity":"error","filePath":"packages/@expo/cli/src/run/ios/appleDevice/AppleDevice.ts","lineNumber":296,"sourceCode":"        debugEvent('apple_device:disconnect_response', { result: res });\n        if (res !== 'OK') {\n          console.warn(\n            'Something went wrong while attempting to disconnect from iOS debug server, you may need to reopen the app manually.'\n          );\n        }\n      }\n\n      return debugServerClient;\n    } else if (result === 'EBusy' || result === 'ENotFound') {\n      debugEvent('apple_device:launch_retry', { tries });\n      tries++;\n      debugServerClient.socket.end();\n      await delayAsync(500);\n    } else {\n      throw new CommandError(`There was an error launching app: ${result}`);\n    }\n  }\n  throw new CommandError('Unable to launch app, number of tries exceeded');\n}\n\n/**\n * iOS 17 introduces a new protocol called RemoteXPC.\n * This is not yet implemented, so we fallback to devicectl.\n *\n * @see https://github.com/doronz88/pymobiledevice3/blob/master/misc/RemoteXPC.md#process-remoted\n */\nasync function launchApp(\n  clientManager: ClientManager,\n  {\n    bundleId,\n    appInfo,\n    detach,\n  }: { bundleId: string; appInfo: IPLookupResult[string]; detach?: boolean }\n) {\n  try {\n    return await launchAppWithUsbmux(clientManager, { appInfo, detach });","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/expo/expo/blob/b09195aac27c9e4a63daaf12dcb6f00b6b2e08ee/packages/@expo/cli/src/run/ios/appleDevice/AppleDevice.ts#L278-L314","documentation":"The companion error to 153: the launch retry loop tolerates 'EBusy'/'ENotFound' for up to 3 attempts with a 500ms backoff (delayAsync). If all three attempts still return a busy/not-found status, the loop exits and throws this CommandError. It means the device/debugserver was persistently unavailable during the launch window.","triggerScenarios":"Three consecutive checkLaunchSuccess() calls returning 'EBusy' or 'ENotFound' within ~1.5s: a device that is still processing a previous install/launch, SpringBoard busy, a long app-attach/signing operation in progress, or a debugserver that is overloaded.","commonSituations":"Rapidly re-running run:ios without letting the previous install finish; a low-powered device (older iPhones) where 500ms×3 is not enough; USB throughput contention with other tools (Xcode, iMazing) holding the device; iOS beta instability.","solutions":["Wait a few seconds and re-run; the device usually frees up.","Close other tools that talk to the device over USB (Xcode, Finder sync, iMazing).","Unplug/replug the device or restart it to reset the debugserver state.","If it persists on iOS 17+, the RemoteXPC/devicectl fallback path may be needed — update @expo/cli to a version with iOS 17 support."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try {\n    return await launchOnDevice(...);\n  } catch (e) {\n    if (e instanceof CommandError && /number of tries exceeded/.test(e.message) && attempt < 2) {\n      await delay(2000); // longer than the inner 500ms backoff\n      continue;\n    }\n    throw e;\n  }\n}","preventionTips":["Avoid back-to-back run:ios on the same device without pausing.","Close Xcode/other USB holders before physical-device runs.","On persistent EBusy, replug or restart the device."],"tags":["ios","physical-device","debugserver","retry"],"backgroundTag":null,"analyzedSha":"b09195aac27c9e4a63daaf12dcb6f00b6b2e08ee","analyzedAt":"2026-08-12T15:59:58.304Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}