expo: `NullPointerException`s when calling `Updates.reloadAsync` with SDK49 in production builds
EDIT: Please see linked comment for repro steps. The cause seems to be from calling reloadAsync from expo-updates.
Minimal reproducible example
https://github.com/patidarsarvesh/ExpoNullPointerIssue
Summary
The problem
We are noticing our app crashing on android with NullPointerException occasionally in production. It is affecting <1% of users, but it’s still consistently happening 1-2 times a day.
Judging from our logs, all crashes seem to be caused by NullPointerException with expo packages. We have seen them so far occur in expo-notifications and expo-location. Here are the stack traces we have:
expo-location
java.lang.NullPointerException: java.lang.NullPointerException
at expo.modules.kotlin.jni.JavaCallback.invoke(JavaCallback.kt)
at expo.modules.kotlin.jni.JavaCallback.invoke(JavaCallback.kt:24)
at expo.modules.kotlin.PromiseKt$toBridgePromise$resolveMethod$1.invoke(Promise.kt:22)
at expo.modules.kotlin.PromiseKt$toBridgePromise$resolveMethod$1.invoke(Promise.kt:22)
at expo.modules.kotlin.PromiseKt$toBridgePromise$1.resolve(Promise.kt:29)
at expo.modules.adapters.react.PromiseWrapper.resolve(PromiseWrapper.java:27)
at expo.modules.location.LocationHelpers$1.onLocationChanged(LocationHelpers.java:157)
at expo.modules.location.LocationModule$1.onLocationResult(LocationModule.java:557)
at com.google.android.gms.internal.location.zzaw.notifyListener(com.google.android.gms:play-services-location@@20.0.0:2)
at com.google.android.gms.common.api.internal.ListenerHolder.zaa(com.google.android.gms:play-services-base@@18.1.0:2)
at com.google.android.gms.common.api.internal.zacb.run
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
expo-notifications
java.lang.NullPointerException: java.lang.NullPointerException
at expo.modules.kotlin.jni.JavaCallback.invoke(JavaCallback.kt)
at expo.modules.kotlin.jni.JavaCallback.invoke(JavaCallback.kt:24)
at expo.modules.kotlin.jni.PromiseImpl.reject(PromiseImpl.kt:87)
at expo.modules.kotlin.PromiseKt$toBridgePromise$1.reject(Promise.kt:41)
at expo.modules.adapters.react.PromiseWrapper.reject(PromiseWrapper.java:36)
at expo.modules.notifications.notifications.presentation.ExpoNotificationPresentationModule$4.onReceiveResult(ExpoNotificationPresentationModule.java:98)
at android.os.ResultReceiver$MyResultReceiver.send(ResultReceiver.java:59)
at android.os.ResultReceiver.send(ResultReceiver.java:93)
at expo.modules.notifications.service.NotificationsService.handleIntent(NotificationsService.kt:650)
at expo.modules.notifications.service.NotificationsService$onReceive$1.invoke(NotificationsService.kt:588)
at expo.modules.notifications.service.NotificationsService$onReceive$1.invoke(NotificationsService.kt:586)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)
java.lang.NullPointerException: java.lang.NullPointerException
at expo.modules.kotlin.jni.JavaCallback.invoke(JavaCallback.kt)
at expo.modules.kotlin.jni.JavaCallback.invoke(JavaCallback.kt:24)
at expo.modules.kotlin.jni.PromiseImpl.reject(PromiseImpl.kt:87)
at expo.modules.kotlin.PromiseKt$toBridgePromise$1.reject(Promise.kt:41)
at expo.modules.adapters.react.PromiseWrapper.reject(PromiseWrapper.java:36)
at expo.modules.notifications.tokens.PushTokenModule$1.onComplete(PushTokenModule.java:72)
at com.google.android.gms.tasks.zzi.run(com.google.android.gms:play-services-tasks@@18.0.2:1)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8855)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
other details
- In production, sentry breadcrumbs suggest the expo-notifications crashes happen on app launch (when we setup the notification handler) and when we fetch the expo push token.
- Logs also suggest that the expo-locations crash happens while we fetch location data from the device
- Crashes so far seen on google and samsung devices, and across many different OS versions (10, 11, 13)
- These crashes somewhat resemble #23382 and #17426, but nothing really matches up with what we’re seeing here
repro
We are having problems consistently reproducing the problem, but here is a repo with what we think are the minimum requirements to trigger the crash.
We have tried everything we can think of to try to reproduce it consistently, such as accepting/rejecting permissions, fetching location data frequently, triggering the push notification handler, fetching the push token frequently, and testing from cold start and on entering foreground.
see https://github.com/expo/expo/issues/24159#issuecomment-1701761218
If you have any tips on debugging native crashes like this we would be happy to apply them and followup. Both in the reproduction repo and in our production app we don’t write any native code ourselves. We have thought about downgrading to expo 48 to see if that fixes the problem but we didn’t want to go through all that effort yet without knowing the root cause.
Environment
- We use eas-build to build our app for ios & android, but the following is one of our local dev machines
expo-env-info 1.0.5 environment info:
System:
OS: macOS 12.6
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.19.0 - ~/.asdf/installs/nodejs/16.19.0/bin/node
Yarn: 1.22.19 - ~/.asdf/installs/nodejs/16.19.0/bin/yarn
npm: 8.19.3 - ~/git_repos/<project_name>/node_modules/.bin/npm
Managers:
CocoaPods: 1.12.0 - /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 22.1, iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1
IDEs:
Android Studio: 2021.3 AI-213.7172.25.2113.9014738
Xcode: 14.1/14B47b - /usr/bin/xcodebuild
npmPackages:
@expo/metro-config: ^0.10.7 => 0.10.7
expo: ^49.0.6 => 49.0.6
react: 18.2.0 => 18.2.0
react-dom: ^18.2.0 => 18.2.0
react-native: 0.72.3 => 0.72.3
react-native-web: ~0.19.6 => 0.19.7
npmGlobalPackages:
eas-cli: 4.1.2
expo-cli: 6.3.10
Expo Workflow: managed
About this issue
- Original URL
- State: closed
- Created 10 months ago
- Reactions: 2
- Comments: 21 (11 by maintainers)
Commits related to this issue
- [core][Android] Fixed random `NullPointerExceptions` when calling `Updates.reloadAsync` (#24442) # Why Fixes https://github.com/expo/expo/issues/24159. # How It turns out that sometimes we'r... — committed to expo/expo by lukmccall 10 months ago
- [core][Android] Fixed random `NullPointerExceptions` when calling `Updates.reloadAsync` (#24442) # Why Fixes https://github.com/expo/expo/issues/24159. # How It turns out that sometimes we're tryi... — committed to expo/expo by lukmccall 10 months ago
We don’t have a solution yet. Most we could do is try to call
refreshAsyncless often.@lukmccall I apologize for the ping on a closed issue, but do you know if there’s a chance this fix can be backported to sdk 49?
I want to reiterate that although we only see logs of this occurring on android with
NullPointExceptions in sentry, I was able to crash IOS as with the same steps. It just seems that sentry is unable to log anything for IOS in that case.@rafavalerio The fix is included in SDK 50, but after requesting it for months I don’t see this fix ever being backported to SDK 49 unfortunately.
Is it possible to include 037566e with the v49 sdk? It’s been merged to main for a month but we’re still dealing with this on v49.
I’m facing the same issue on Android at first app lunch…
I am experiencing the same issue. Here’s some of the stack traces:
Expo updates:
Expo Location