Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

com.facebook.infer.annotation.Assertions.assertNotNull Assertions.java, line 19 java.lang.AssertionError: Tried to start a task on a react context that has already been destroyed #266

Closed
ghost opened this issue Dec 13, 2021 · 28 comments · Fixed by #1168

Comments

@ghost
Copy link

ghost commented Dec 13, 2021

I am facing a crash in the react-native android app which is not able to reproduce.
The crash is happening only in production. I tried different things but not able to find the cause of the problem
Here is the stack trace I got in App-Center Crashlytics

Assertions.java, line 19
java.lang.AssertionError: Tried to start a task on a react context that has already been destroyed
com.facebook.infer.annotation.Assertions.assertNotNull Assertions.java:19
com.facebook.react.jstasks.HeadlessJsTaskContext.startTask HeadlessJsTaskContext.java:98
com.facebook.react.jstasks.HeadlessJsTaskContext.startTask HeadlessJsTaskContext.java:87
io.invertase.notifee.NotifeeReactUtils.lambda$startHeadlessTask$1 NotifeeReactUtils.java:161
io.invertase.notifee.-$$Lambda$NotifeeReactUtils$KgQWh76krkFzoFdkyOWh2Uc96Ig.call
io.invertase.notifee.-$$Lambda$LL5T3_qcdZ0KgAbnpHFtVQIbufQ.run
android.os.Handler.handleCallback Handler.java:873
android.os.Handler.dispatchMessage Handler.java:99
android.os.Looper.loop Looper.java:201
android.app.ActivityThread.main ActivityThread.java:6826
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:547
com.android.internal.os.ZygoteInit.main ZygoteInit.java:873

As far I can see this crash is related to some HeadlessJsTaskContext. I am using @notifee/react-native for handling notifications coming from FCM. all the notifications states (Foreground, Background and Killed ) are working fine when tested but this crash count is kept increasing

@mikehardy
Copy link
Collaborator

@helenaford I looked into this but could not easily come up with the repair.

The root cause is that the react context fetched with getReactContext() at time of task init in the task is null, which react-native rightly asserts on (and throws)

But there is a lot of machinery with regard to initializing the react context, and a separate call below line 161 where null is tested (outside of task init) and if null it is initialized

I find all of that machinery and the out-of-task null check confusing, so while I'd propose just testing for null and logging a warning then exiting during headless task init, I couldn't say with any confidence that was correct

@helenaford
Copy link
Member

helenaford commented Dec 13, 2021

@mikehardy yeah, this stuff is tricky 🤔 @SaiKrishna1834 do you have any information on the device type, model, or android version this crash is happening for?

Also, where are you calling notifee.onBackgroundEvent? Can you paste the notification payload you pass to notifee.displayNotification?

@ghost
Copy link
Author

ghost commented Dec 14, 2021

@mikehardy, this crash is happening mostly in all types of devices. attaching the screenshot of the crash report.

Screenshot 2021-12-14 at 8 56 46 AM

we are calling notifee.onBackgroundEvent in app index.js file and the payload we are passing to display notification is let notificationObj = { title: notification.notification.title, body: notification.notification.body, data: { title: notification.notification.title, body: `notification.notification.body,` }, _notificationId: Math.random().toString(), }.
Everything is fine while displaying the notification and redirection in android. but not able to find the reason for the crash.

@mikehardy
Copy link
Collaborator

It appeared to me the code definitely needed repair - I could easily see how a null found it into the place where a null was then asserted as not null, I just couldn't personally figure out what all the background context initialization machinery was doing is all ;-)

@julestruong
Copy link

any news on this ?
The error happens to me too. But i'm not displaying any notification , i just installed it.

@github-actions
Copy link

github-actions bot commented Dec 6, 2022

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Dec 21, 2022
@mohammad-goldast
Copy link

mohammad-goldast commented Dec 8, 2024

This topic is not stale.
I have the same issue on Android with RN 0.76.3 and Notifee 9.3.1

@mikehardy
Copy link
Collaborator

Interesting. Because of an upstream react-native new arch + headlessJS issue I actually have a reproducer for headlessJS task startup. Can likely investigate. Reproduction is the hardest part.

@mohammad-goldast
Copy link

@mikehardy Thanks for doing an investigation on it.
Is there any quick/easy way to avoid this crash for now? (We have passed our deadline and want to publish the app ASAP.)
If you can help me to change something to fix this for now, It would be great & appreciated.

After that we can work on the reproduction and fixing things.

@mikehardy
Copy link
Collaborator

Hey @mohammad-goldast in the related issue you posted some code but it is definitely not a minimal reproducible example. It has imports for all sorts of things and none of those are include. A reproducible example would be nothing but an index.js + App.tsx that import no other code (or at most just the notifee and react-native-firebase code) and has everything needed to trigger the conditions that cause the problem (like, a button that sets things up) and clear instructions on how to then trigger the problem

For instance, in this case you might have just the notifee background handler in index.js and an App.tsx that creates a trigger notification or whatever kind of notification causes it for you, then...I don't know exactly how you trigger it but I imagine you use task switcher to swipe the app away, then interact with the notification?

After that we can work on the reproduction and fixing things.

Unfortunately that's not really how it works. You can't fix something you can't reproduce. The quick and easy way to fix it is to reproduce it.

@mohammad-goldast
Copy link

Thanks @mikehardy for your effort.

I just created a new/pure react-native project (0.76.5) and installed only notifee (9.3.1) and wrote some simple code to reproduce the crash.

Repo: https://github.com/mohammad-goldast/reproduce-notifee-reactnative-crash

Also, what I saw new in the JavaScript Log, is this error:

Error: Exception in HostFunction: Could not enqueue microtask because they are disabled in this runtime, js engine: hermes
LOG  Failed to print error:  Exception in HostFunction: Could not enqueue microtask because they are disabled in this runtime

But same as the past, the crashes on my real Android device is:

Assertions.java, line 19
java.lang.AssertionError: Tried to start a task on a react context that has already been destroyed
com.facebook.infer.annotation.Assertions.assertNotNull Assertions.java:19
com.facebook.react.jstasks.HeadlessJsTaskContext.startTask HeadlessJsTaskContext.java:98
com.facebook.react.jstasks.HeadlessJsTaskContext.startTask HeadlessJsTaskContext.java:87
io.invertase.notifee.NotifeeReactUtils.lambda$startHeadlessTask$1 NotifeeReactUtils.java:161
io.invertase.notifee.-$$Lambda$NotifeeReactUtils$KgQWh76krkFzoFdkyOWh2Uc96Ig.call
io.invertase.notifee.-$$Lambda$LL5T3_qcdZ0KgAbnpHFtVQIbufQ.run
android.os.Handler.handleCallback Handler.java:873
android.os.Handler.dispatchMessage Handler.java:99
android.os.Looper.loop Looper.java:201
android.app.ActivityThread.main ActivityThread.java:6826
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:547
com.android.internal.os.ZygoteInit.main ZygoteInit.java:873

Now, if I can do something else just ping me.

@MaxToyberman
Copy link

@mohammad-goldast try this patch: (it should be fixed in react-native 0.76.5)

facebook/react-native@4560fc0

@mikehardy
Copy link
Collaborator

@MaxToyberman his reproducible example is new arch, so that patch shouldn't matter, it was an old-arch fix

https://github.com/mohammad-goldast/reproduce-notifee-reactnative-crash/blob/aeccee65700a609d35d32b1cda28b34ef0a46a05/android/gradle.properties#L35

@mohammad-goldast
Copy link

@MaxToyberman
Thanks man for your response but I disabled the "newArchitecture" from the gradle file and upgraded RN to 0.76.5 and applied the patch but I am still getting these errors:

 FATAL EXCEPTION: main
 Process: com.ifsguide.app.staging, PID: 14432
 java.lang.AssertionError: Tried to start a task on a react context that has already been destroyed
 	at com.facebook.infer.annotation.Assertions.assertNotNull(Assertions.java:19)
 	at com.facebook.react.jstasks.HeadlessJsTaskContext.startTask(HeadlessJsTaskContext.java:102)
 	at com.facebook.react.jstasks.HeadlessJsTaskContext.startTask(HeadlessJsTaskContext.java:91)
 	at io.invertase.notifee.NotifeeReactUtils.lambda$startHeadlessTask$1(NotifeeReactUtils.java:194)
 	at io.invertase.notifee.NotifeeReactUtils$$ExternalSyntheticLambda1.call(D8$$SyntheticClass:0)
 	at io.invertase.notifee.NotifeeReactUtils$2$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
 	at android.os.Handler.handleCallback(Handler.java:942)
 	at android.os.Handler.dispatchMessage(Handler.java:99)
 	at android.os.Looper.loopOnce(Looper.java:211)
 	at android.os.Looper.loop(Looper.java:300)
 	at android.app.ActivityThread.main(ActivityThread.java:8503)
 	at java.lang.reflect.Method.invoke(Native Method)
 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:561)
 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:954)
Process is going to kill itself!
java.lang.Exception
	at android.os.Process.killProcess(Process.java:1344)
	at com.android.internal.os.RuntimeInit$KillApplicationHandler.uncaughtException(RuntimeInit.java:174)
	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1071)
	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1066)
	at java.lang.Thread.dispatchUncaughtException(Thread.java:2306)

CC: @mikehardy

@mikehardy
Copy link
Collaborator

@mohammad-goldast unfortunately I was pretty certain that fix wasn't going to affect you as it was very specifically old-arch and your reproducer (which is excellent by the way) is definitely showing a problem, and definitely on the new arch.

So I see the problem, I'm just not sure exactly what is causing it in our internals yet so I'm not sure exactly how to handle it. Current hypothesis is a race condition between the react-native init pathway and the headlessJS context startup and I'm testing that but don't have anything conclusive yet.

@gituser8796
Copy link

@mikehardy In our latest rollout, using React Native 0.76.5 with the new architecture, we are experiencing this crash as well. For context, everything worked well when we were using React Native 0.75.4 with the old architecture and Notifee 7.8.2.

We have also moved the setup of notification handlers to the top of the index file, as suggested here: facebook/react-native#47570 (comment). However, this did not resolve the issue.

@mikehardy
Copy link
Collaborator

Closing in on it - definitely a race condition with React Native background app startup / context creation and the Notifee native code attempting to use the context in the headless task in the new architecture.

I've got some not-production-ready code that functions and no longer crashes but I can't publish it in the state it is in, and it's pretty complex to handle this case. Will clean it up and get a fix out once I think through how to structure it well

@mikehardy
Copy link
Collaborator

#1168 should fix this thing again - ridiculous amount of complexity now in order to correctly wait on react-native startup so we can get a valid ReactContext, while queuing any of our events that come in and need it, if it isn't ready yet. But that's mobile programming

@mikehardy
Copy link
Collaborator

fix released as v9.1.4, I hope it works! Did my best testing for new arch plus regression on old arch, seems to work for me. Thanks again to @mohammad-goldast for your reproduction, very helpful.

@mohammad-goldast
Copy link

Thanks @mikehardy for your effort.
I installed 9.1.4 and the crash has been resolved and it doesn't trigger the headlessTask error anymore.
But there is still another problem, the app doesn't open on Android by tapping on a notification. I am not sure this issue is because of Notifee or React-Native. if you can help I will appreciate it.

I tested this issue on 2 real android devices to make sure.
Updated Repo: https://github.com/mohammad-goldast/reproduce-notifee-reactnative-crash

@mohammad-goldast
Copy link

Update:
BTW, I'd installed react-native-push-notification package and handled Android schedule notifications on it.
It works and my app opens by tapping on a notification.

@wilmxre
Copy link

wilmxre commented Dec 17, 2024

@mikehardy i recently faced this crash report too after i upgraded from expo 50 (react-native 0.73.4) to expo 51 (react-native 0.74.5). i don't use notifee, but @react-native-firebase/messaging with version 21.6.1.

my reproduction was the following: the app was in killed & sleep mode, it got a silent push notification (from an incoming call) which should in normal circumstances wake up the device, open the app and show an incoming call activity. instead, the device seems to wake up for a brief second, then goes back to sleep, then it wakes up again, then goes back to sleep. if i open the device manually i get a message that my app has crashed. i checked with logcat and got what it seems the same crash report as the one in this issue:

 java.lang.RuntimeException: Unable to pause activity {com.x.y/com.x.y.MainActivity}: java.lang.reflect.InvocationTargetException
    at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:5780)
    at android.app.ActivityThread.performPauseActivity(ActivityThread.java:5731)
    at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:5683)
    at android.app.servertransaction.PauseActivityItem.execute(PauseActivityItem.java:48)
    at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:180)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:98)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:230)
    at android.os.Looper.loop(Looper.java:319)
    at android.app.ActivityThread.main(ActivityThread.java:8919)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
    Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at expo.modules.ReactActivityDelegateWrapper.invokeDelegateMethod(ReactActivityDelegateWrapper.kt:328)
    at expo.modules.ReactActivityDelegateWrapper.onPause(ReactActivityDelegateWrapper.kt:203)
    at com.facebook.react.ReactActivity.onPause(ReactActivity.java:53)
    at android.app.Activity.performPause(Activity.java:9188)
    at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1657)
    at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:5770)
    at android.app.ActivityThread.performPauseActivity(ActivityThread.java:5731) 
    at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:5683) 
    at android.app.servertransaction.PauseActivityItem.execute(PauseActivityItem.java:48) 
    at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45) 
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:180) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:98) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:230) 
    at android.os.Looper.loop(Looper.java:319) 
    at android.app.ActivityThread.main(ActivityThread.java:8919) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103) 
    
       Caused by: java.lang.AssertionError
        at com.facebook.infer.annotation.Assertions.assertCondition(Assertions.java:82)
        at com.facebook.react.ReactInstanceManager.onHostPause(ReactInstanceManager.java:597)
        at com.facebook.react.ReactDelegate.onHostPause(ReactDelegate.java:134)
        at com.facebook.react.ReactActivityDelegate.onPause(ReactActivityDelegate.java:134)
                                                                                                    	

this crash is only happening if the device is in sleep mode and the app was previously killed. if the device is on, but the app was previously killed, the crash is not happening.

do you think it would be better to raise a new issue under the react-native-firebase repo and providing a reproducible repo?

i assume this crash is also caused by the react-native initialization during headlessJS

@mikehardy
Copy link
Collaborator

@mohammad-goldast you need to set a press action --> https://github.com/invertase/notifee/blob/main/docs-react-native/react-native/docs/android/interaction.md#simple-behaviour

@mikehardy
Copy link
Collaborator

Hey @wilmxre 👋

do you think it would be better to raise a new issue under the react-native-firebase repo and providing a reproducible repo?

Yes - if you are not using notifee, the issue doesn't belong here - and I don't see Notifee in the stack. That stack doesn't look familiar either, curious why you assert it looks the same? It has almost nothing in common with the original stack here from what I see?

I assert that in the absence of any react-native-firebase frames in the stack trace (I don't see any?) that it doesn't actually belong there either, this looks like an upstream react-native issue. You'll need a reproducer though. Unfortunately reproducers that requires react-native-firebase FCM are very very difficult for react-native upstream devs to work with because they will not have any firebase projects setup and registering devices for delivery of FCM is difficult as well.

I suggest a better reproducer style based on what worked for me is to "fake" the FCM by using a combination of a receiver, a service, and adb. You can use an API24 emulator for this so you don't have background service start restrictions. You set up a service that does something, a receiver that can receive a test intent, then you use adb to send the test intent and it should attempt to wake the app up and cause the crash if you have the scenario right.

You can see this here - https://github.com/mikehardy/old-arch-android-receiver-boot-crash (this is the commit where I add the receiver+service to MainApplication.kt, the README documents how to trigger things mikehardy/old-arch-android-receiver-boot-crash@245f946 )

@wilmxre
Copy link

wilmxre commented Dec 18, 2024

thank you @mikehardy for your detailed reply and sorry for spamming this thread with my issue, i thought it is somewhat related to what was discussed here.

for anyone who might come here because my reply, the PR in #3309 fixed my issue.

these were my reproduction steps:

  1. App is closed
  2. Device is locked
  3. I get a call notification
  4. The device wakes up for a brief second and presents me to unlock the lock screen
  5. I unlock the device (or not)
  6. App crashes

@mikehardy
Copy link
Collaborator

Wow that's subtle - I read that PR. Glad you found your root cause there @wilmxre and of course I'm glad that it wasn't here - happy to fix bugs in RNFB and Notifee but this has been such a struggle, I really want the headlessJS stuff to go to sleep for a while 😆

@MaxToyberman
Copy link

MaxToyberman commented Dec 20, 2024

Hi @mikehardy

After this fix i have started seeing many errors in Crashlytics with the following stack trace:

Fatal Exception: com.facebook.react.bridge.ObjectAlreadyConsumedException
Map already consumed

com.facebook.react.bridge.WritableNativeMap.mergeNativeMap (WritableNativeMap.kt)
com.facebook.react.bridge.WritableNativeMap.merge (WritableNativeMap.kt:47)
com.facebook.react.bridge.WritableNativeMap.copy (WritableNativeMap.kt:52)
com.facebook.react.jstasks.HeadlessJsTaskConfig.<init> (HeadlessJsTaskConfig.java:90)
com.facebook.react.jstasks.HeadlessJsTaskContext.startTask (HeadlessJsTaskContext.java:113)
com.facebook.react.jstasks.HeadlessJsTaskContext.startTask (HeadlessJsTaskContext.java:91)
io.invertase.notifee.HeadlessTask.invokeStartTask (HeadlessTask.java:235)
io.invertase.notifee.HeadlessTask.lambda$drainTaskQueue$0 (HeadlessTask.java:347)
io.invertase.notifee.HeadlessTask.$r8$lambda$TfM4uS4TmugyY-kRBF4YHDzDJ04
io.invertase.notifee.HeadlessTask$$ExternalSyntheticLambda0.run (D8$$SyntheticClass)

Unfortunately i cant reproduce this issue locally,
After looking at the stack trace i saw that there is a WritableMap in the TaskConfig class
and i think that instead of

      // Insert our custom taskId for users to call finishHeadlessTask(taskId) with.
      params.putInt("taskId", mTaskId);
      mParams = params;

we need:

     // Create a copy of the original params map to ensure it is not modified
      mParams = params.copy();  // Using copy() to create a new independent map

      // Insert our custom taskId for users to call finishHeadlessTask(taskId) with.
      mParams.putInt("taskId", mTaskId);

What do you think ?
If it is acceptable, i can open a PR.

Thanks

@mikehardy
Copy link
Collaborator

Hey @MaxToyberman indeed - I wasn't even aware this was a possibility until I saw mention of it in transistorsoft/react-native-background-geolocation#2235 (comment)

I attempted something that was directed at this yesterday in #1176 which was just released as v9.1.8 but now that I see your code snippet I'm not sure it's on target.

Let me peel your comment off to a new issue and we'll discuss over there

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants