Description
Recurrence of closed, locked #10187 (also #10533 and #28184): resolving a Debug bundle URL can synchronously wait for Metro on the launch main thread, and iOS kills the app before it can display a bundle-loading error.
Observed with React Native 0.86.3, Expo SDK 57 (Bridgeless/Hermes), Xcode 27, and iOS 27.0.1 on a physical iPhone. The termination is EXC_CRASH / SIGKILL, FRONTBOARD 0x8BADF00D, scene-create watchdog transgression, with a 10-second wall-clock allowance.
React Native Version
0.86.3 (device reproduction). 0.87.1 and current main were source-inspected, not device-tested.
Affected Platforms
Runtime - iOS; Build - MacOS.
MANDATORY Reproducer
Public application before the workaround. Install dependencies and use npx expo prebuild --platform ios --no-install; its generated Debug AppDelegate uses the standard provider call. The reproduction is native-only and happens before JS loads.
Steps to reproduce
- Use the standard Debug iOS entry point that calls
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ...) during root-view/scene creation. No application JavaScript is needed to reach this path.
- Configure
RCT_jsLocation to an unreachable Metro host. Ensure the build-time ip.txt fallback host is also unreachable (for example, move the phone away from the development network). Launch outside the Xcode debugger.
- The main-thread path is
bundleURL → jsBundleURLForBundleRoot → packagerServerHostPort → isPackagerRunning, first for the configured host, then for the guessed host.
- Each
/status request can wait up to 6 seconds plus 2 seconds of grace. Two sequential waits exceed scene creation's 10-second budget. Expected: a responsive scene and normal bundle-loading error, not a watchdog kill.
Current source
The synchronous semaphore and sequential probes remain in 0.87.1 and main at 73f420430c08a9d8724ad569623600d0f58f1688. An asynchronous status API exists, but URL discovery still calls the synchronous API.
A local application-boundary workaround selects the configured host (otherwise ip.txt/localhost) without probing, uses the provider's class URL-construction API, and lets the normal asynchronous bundle loader report connection errors. This intentionally does not retain automatic fallback from a stale configured host. A generic upstream fix should remove launch-main-thread network waits while deciding how to preserve discovery/fallback semantics; shortening the per-request timeout is not sufficient.
Duplicate search
Searched open and closed React Native and Expo issues for isPackagerRunning, 0x8BADF00D, and packager/watchdog launch terms. #10187 is the direct match but is locked; #10533 links to it. Expo #9408 and #17698 describe different TestFlight/background crash paths. Reporting the current-version recurrence here rather than creating an unrelated Expo issue.
Output of npx @react-native-community/cli info
Public-safe excerpt (machine paths omitted):
System: macOS 27.0.1; arm64 Apple M4 Max
Node: 24.20.0
npm: 11.19.0
Xcode: 27.0/27A266a
iOS SDK: 27.0
React: 19.2.3
React Native: 0.86.3
Stacktrace or Logs
EXC_CRASH / SIGKILL
FRONTBOARD 0x8BADF00D
scene-create watchdog transgression: exhausted real (wall clock) time allowance of 10.00 seconds
The native bundle-URL callback is invoked on the scene-create main-thread path; isPackagerRunning waits synchronously on its URLSession completion semaphore. The reproduction does not require application JS.
Posted on behalf of @schickling
| field |
value |
agent_identity |
agent/compoundingtech/st-ios |
session |
mbp2025.01a1069f |
agent_persona |
generalist |
agent_supervisor |
unavailable |
agent_tool |
OMP |
agent_tool_version |
18.6.0 |
agent_runtime |
OMP 18.6.0 |
agent_model |
anthropic/claude-opus-5-5 |
worktree |
smalltalk/2026-10-07-ios-metro-launch-watchdog |
tooling_profile |
dotfiles@407b692 |
Description
Recurrence of closed, locked #10187 (also #10533 and #28184): resolving a Debug bundle URL can synchronously wait for Metro on the launch main thread, and iOS kills the app before it can display a bundle-loading error.
Observed with React Native 0.86.3, Expo SDK 57 (Bridgeless/Hermes), Xcode 27, and iOS 27.0.1 on a physical iPhone. The termination is
EXC_CRASH / SIGKILL,FRONTBOARD 0x8BADF00D,scene-create watchdog transgression, with a 10-second wall-clock allowance.React Native Version
0.86.3 (device reproduction). 0.87.1 and current main were source-inspected, not device-tested.
Affected Platforms
Runtime - iOS; Build - MacOS.
MANDATORY Reproducer
Public application before the workaround. Install dependencies and use
npx expo prebuild --platform ios --no-install; its generated Debug AppDelegate uses the standard provider call. The reproduction is native-only and happens before JS loads.Steps to reproduce
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ...)during root-view/scene creation. No application JavaScript is needed to reach this path.RCT_jsLocationto an unreachable Metro host. Ensure the build-timeip.txtfallback host is also unreachable (for example, move the phone away from the development network). Launch outside the Xcode debugger.bundleURL→jsBundleURLForBundleRoot→packagerServerHostPort→isPackagerRunning, first for the configured host, then for the guessed host./statusrequest can wait up to 6 seconds plus 2 seconds of grace. Two sequential waits exceed scene creation's 10-second budget. Expected: a responsive scene and normal bundle-loading error, not a watchdog kill.Current source
The synchronous semaphore and sequential probes remain in 0.87.1 and main at 73f420430c08a9d8724ad569623600d0f58f1688. An asynchronous status API exists, but URL discovery still calls the synchronous API.
A local application-boundary workaround selects the configured host (otherwise
ip.txt/localhost) without probing, uses the provider's class URL-construction API, and lets the normal asynchronous bundle loader report connection errors. This intentionally does not retain automatic fallback from a stale configured host. A generic upstream fix should remove launch-main-thread network waits while deciding how to preserve discovery/fallback semantics; shortening the per-request timeout is not sufficient.Duplicate search
Searched open and closed React Native and Expo issues for
isPackagerRunning,0x8BADF00D, and packager/watchdog launch terms. #10187 is the direct match but is locked; #10533 links to it. Expo #9408 and #17698 describe different TestFlight/background crash paths. Reporting the current-version recurrence here rather than creating an unrelated Expo issue.Output of
npx @react-native-community/cli infoPublic-safe excerpt (machine paths omitted):
Stacktrace or Logs
The native bundle-URL callback is invoked on the scene-create main-thread path;
isPackagerRunningwaits synchronously on its URLSession completion semaphore. The reproduction does not require application JS.Posted on behalf of @schickling
agent_identitysessionagent_personaagent_supervisoragent_toolagent_tool_versionagent_runtimeagent_modelworktreetooling_profile