Repository navigation
[Android][Bridgeless] Destroying the Activity during a JS reload leaves ReactContext.getCurrentActivity() null until the app is backgrounded #59473
Description
Description
With the New Architecture (bridgeless ReactHostImpl), if the host Activity is destroyed while a JS reload is still running, the reload finishes by resuming the new ReactContext with no Activity and marks the lifecycle RESUMED. When the app is reopened, ReactHost.onHostResume(activity) returns early because the state is "already resumed", so the new context never receives the new Activity.
From then on ReactContext.getCurrentActivity() is null for every native module, until the app goes to the background and comes back (onHostPause resets the state, and the next resume passes the Activity). React Native's own PermissionsAndroid.request() then rejects with E_INVALID_ACTIVITY ("Tried to use permissions API while not attached to an Activity."). We first hit it through a third-party recorder module whose constructor needs the current Activity.
This is likely the root cause of #46201 ("Tried to show an alert while not attached to an Activity", New Architecture). That issue was closed because it couldn't be reproduced; later comments report the same intermittent failure, fixed by restarting the app. Alert reads getCurrentActivity() the same way.
Where it goes wrong (packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/, unchanged on main at the time of writing):
ReactHostImpl.kt, in the lifecycle step after instance creation (if (isReloading && !isManagerResumed), ~L1112 onmain, L1124 in 0.86.3):isManagerResumedis read when the reload finishes. If the Activity was destroyed meanwhile,onHostDestroy(activity)→moveToHostDestroy()has already set the state toBEFORE_CREATEandcurrentActivity = null. The reload branch then callsreactLifecycleStateManager.moveToOnHostResume(reactContext, currentActivity)withcurrentActivity == null, which callsReactContext.onHostResume(null)and sets the state toRESUMED. The comment above it assumes that during a reload "we must be on a React Native screen"; that no longer holds once the Activity is gone.ReactLifecycleStateManager.moveToOnHostResume()returns immediately when the state is alreadyRESUMED.- When the user reopens the app,
ReactHostImpl.onHostResume(activity)updatesReactHostImpl.currentActivity, but because of (2) it never callsReactContext.onHostResume(activity).ReactContext.mCurrentActivity, a weak reference, stays null. ReactContext.getCurrentActivity()returnsnulluntil the next pause/resume cycle or anonNewIntent.
In release builds this needs a JS reload, so it mainly affects development (Fast Refresh full reloads, R-R, the dev menu). Apps that reload JS programmatically, for example with OTA updates, could hit it in production.
Possible fixes (either would avoid the stale state):
- Resume the context in the reload branch only when an Activity exists:
if (isReloading && !isManagerResumed && currentActivity != null). - Or, in
moveToOnHostResume(), when the state is alreadyRESUMEDbutcurrentContext.currentActivity !== activity, still callcurrentContext.onHostResume(activity).
Steps to reproduce
- Install the reproducer with
yarn android(debug build, Metro running fromyarn start). The reproducer'smetro.config.jsdelays bundle responses by 1.5 s. That emulates a real app's reload time; without it this tiny app reloads faster than Android tears down the Activity. - Tap Call PermissionsAndroid.request(). It resolves (CAMERA isn't declared, so there's no dialog).
- Trigger a JS reload and press Back while it's running:
adb shell "input keyevent 46 46; sleep 0.3; input keyevent 4"(R, R = reload, then Back). The Activity is destroyed before the reload finishes. - Reopen the app from the launcher icon. Don't use a deep link:
onNewIntentupdates the context's Activity and hides the bug. - Tap the button. It rejects with
E_INVALID_ACTIVITY: Tried to use permissions API while not attached to an Activity. - Press Home, reopen the app and tap again. It resolves.
Reproduced twice out of two runs on react-native 0.88.0 (Samsung Galaxy S21 Ultra, Android 15).
React Native Version
0.88.0
Affected Platforms
Runtime - Android
Areas
Bridgeless - The New Initialization Flow
Output of npx @react-native-community/cli info
System:
OS: macOS 27.0.1
CPU: (8) arm64 Apple M1 Pro
Memory: 142.88 MB / 16.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 24.21.0
path: /Users/mixin/.nvm/versions/node/v24.21.0/bin/node
Yarn:
version: 1.22.22
path: /Users/mixin/.nvm/versions/node/v24.21.0/bin/yarn
npm:
version: 11.19.0
path: /Users/mixin/.nvm/versions/node/v24.21.0/bin/npm
Watchman:
version: 2026.06.29.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.16.2
path: /opt/homebrew/opt/ruby/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 27.0
- iOS 27.0
- macOS 27.0
- tvOS 27.0
- visionOS 27.0
- watchOS 27.0
Android SDK:
API Levels:
- "31"
- "33"
- "34"
- "35"
- "36"
- "37"
Build Tools:
- 30.0.3
- 33.0.1
- 34.0.0
- 35.0.0
- 35.0.1
- 36.0.0
- 36.0.0
- 37.0.0
System Images:
- android-35 | Google Play ARM 64 v8a
- android-36 | Wear OS 6.0 ARM 64 v8a
- android-36 | Google Play ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2026.1 AI-261.26222.65.2613.15948027
Xcode:
version: 27.0/27A266a
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.19
path: /usr/bin/javac
Ruby:
version: 4.0.1
path: /opt/homebrew/opt/ruby/bin/ruby
npmPackages:
"@react-native-community/cli":
installed: 20.2.0
wanted: 20.2.0
react:
installed: 19.3.0
wanted: 19.3.0
react-native:
installed: 0.88.0
wanted: 0.88.0
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: Not found
newArchEnabled: false
Stacktrace or Logs
From the reproducer (react-native 0.88.0), adb logcat filtered to React Native's state-tracker lines:
10:30:34.311 W/unknown:BridgelessReact: ReactHost{0}.getOrCreateReloadTask(): Calling ReactContext.onHostPause()
10:30:34.749 W/unknown:BridgelessReact: ReactHost{0}.onHostPause(activity)
10:30:35.647 W/unknown:BridgelessReact: ReactHost{0}.onHostDestroy(activity)
10:30:36.264 W/unknown:BridgelessReact: ReactHost{0}.ReactContext.onHostResume() <- reload finishes after the destroy and resumes the context with no Activity
10:30:55.141 W/unknown:BridgelessReact: ReactHost{0}.onHostResume(activity) <- reopened from the launcher; no ReactContext.onHostResume() follows
JS: PermissionsAndroid.request() rejected: E_INVALID_ACTIVITY Tried to use permissions API while not attached to an Activity.
--- Home, then reopen ---
10:31:19.888 W/unknown:BridgelessReact: ReactHost{0}.onHostPause(activity)
10:31:19.895 W/unknown:BridgelessReact: ReactHost{0}.ReactContext.onHostPause()
10:31:22.375 W/unknown:BridgelessReact: ReactHost{0}.onHostResume(activity)
10:31:22.387 W/unknown:BridgelessReact: ReactHost{0}.ReactContext.onHostResume() <- context gets the Activity again; the request resolves
Device: Samsung Galaxy S21 Ultra (SM-G998B), Android 15, debug build, New Architecture.
MANDATORY Reproducer
https://github.com/mixin27/rn-reload-current-activity
Screenshots and Videos

Activity