OneSignal-Android-SDK icon indicating copy to clipboard operation
OneSignal-Android-SDK copied to clipboard

[Bug]: Model.getStringProperty$default crash due to NullPointerException

Open fanwgwg opened this issue 2 years ago • 13 comments

What happened?

Sometimes at app start, the app would randomly crash (saw 2 times out of ~50 attempts) at app open.

Crash:

Error attempting to execute operation: [com.onesignal.core.internal.operations.impl.OperationRepo$OperationQueueItem@24a7f5e]
                                                                                                    java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
                                                                                                    	at com.onesignal.common.modeling.Model.getStringProperty(Model.kt:215)
                                                                                                    	at com.onesignal.common.modeling.Model.getStringProperty$default(Model.kt:215)
                                                                                                    	at com.onesignal.common.modeling.Model.getId(Model.kt:61)
                                                                                                    	at com.onesignal.common.modeling.ModelStore.get(ModelStore.kt:63)
                                                                                                    	at com.onesignal.common.modeling.SingletonModelStore.getModel(SingletonModelStore.kt:22)
                                                                                                    	at com.onesignal.user.internal.operations.impl.executors.RefreshUserOperationExecutor.getUser(RefreshUserOperationExecutor.kt:110)
                                                                                                    	at com.onesignal.user.internal.operations.impl.executors.RefreshUserOperationExecutor.access$getUser(RefreshUserOperationExecutor.kt:27)
                                                                                                    	at com.onesignal.user.internal.operations.impl.executors.RefreshUserOperationExecutor$getUser$1.invokeSuspend(Unknown Source:15)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:33)
                                                                                                    	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:102)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
                                                                                                    	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
                                                                                                    	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
                                                                                                    	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
                                                                                                    	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
                                                                                                    	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source:1)
                                                                                                    	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
                                                                                                    	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source:1)
                                                                                                    	at com.onesignal.common.threading.ThreadUtilsKt$suspendifyOnThread$2.invoke(ThreadUtils.kt:74)
                                                                                                    	at com.onesignal.common.threading.ThreadUtilsKt$suspendifyOnThread$2.invoke(ThreadUtils.kt:73)
                                                                                                    	at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

Steps to reproduce?

Described above

What did you expect to happen?

App should not crash

OneSignal Android SDK version

5.0.1

Android version

13

Specific Android models

No response

Relevant log output

No response

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

fanwgwg avatar Sep 15 '23 09:09 fanwgwg

Hi @fanwgwg thank you for your patience here! We are still attempting to reproduce this crash. Is there any additional information you might be able to share about when you experience this? Appreciate it!

jennantilla avatar Sep 27 '23 21:09 jennantilla

@jennantilla I don't have a consistent way to reproduce it, as I've only encountered at a chance like 2 out of 50. What my app does is that on every activity resume, we refresh OneSignal by doing

if (isSignedIn) {
  OneSignal.login(authInfo.getSignedIn().getUserId()); 
  OneSignal.getUser().addEmail(authInfo.getSignedIn().getEmail());
  OneSignal.getUser().setLanguage(AppUtils.getDeviceLocaleInSupportedLocale().toLanguageTag());
} else {
  OneSignal.logout();
}

However, now that our app is released, we're also seeing this crash encountered by users and reported by crashlytics. Looking at the logs, they all happen at very early stage of app startup.

fanwgwg avatar Sep 28 '23 04:09 fanwgwg

Hi, I'm observing same issue in production.

SDK version : [5.0.0, 5.99.99]

Caused by java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
       at com.onesignal.common.modeling.Model.getStringProperty(Model.kt:215)
       at com.onesignal.common.modeling.Model.getStringProperty$default(Model.kt:215)
       at com.onesignal.core.internal.config.ConfigModel.getAppId(ConfigModel.kt:19)
       at com.onesignal.session.internal.session.impl.SessionListener.onSessionStarted(SessionListener.kt:43)
       at com.onesignal.session.internal.session.impl.SessionService$onFocus$1.invoke(SessionService.kt:81)
       at com.onesignal.session.internal.session.impl.SessionService$onFocus$1.invoke(SessionService.kt:81)
       at com.onesignal.common.events.EventProducer.fire(EventProducer.kt:44)
       at com.onesignal.session.internal.session.impl.SessionService.onFocus(SessionService.kt:81)
       at com.onesignal.core.internal.application.impl.ApplicationService$handleFocus$1.invoke(ApplicationService.kt:341)
       at com.onesignal.core.internal.application.impl.ApplicationService$handleFocus$1.invoke(ApplicationService.kt:341)
       at com.onesignal.common.events.EventProducer.fire(EventProducer.kt:44)
       at com.onesignal.core.internal.application.impl.ApplicationService.handleFocus(ApplicationService.kt:341)
       at com.onesignal.core.internal.application.impl.ApplicationService.onActivityStarted(ApplicationService.kt:149)
       at android.app.Application.dispatchActivityStarted(Application.java:219)
       at android.app.Activity.onStart(Activity.java:1322)
       at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:345)
       at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:251)
       at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1340)
       at android.app.Activity.performStart(Activity.java:7364)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3281)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3429)
       at android.app.ActivityThread.-wrap12()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2009)
       at android.os.Handler.dispatchMessage(Handler.java:109)
       at android.os.Looper.loop(Looper.java:166)
       at android.app.ActivityThread.main(ActivityThread.java:7555)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:469)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963)

dmytroreutov avatar Oct 03 '23 07:10 dmytroreutov

I'm also encountering the same crash, One Signal version 5.0.3. Stack trace:

Fatal Exception: java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
       at com.onesignal.common.modeling.Model.getStringProperty(Model.java:11)
       at com.onesignal.common.modeling.Model.getStringProperty$default(Model.java:7)
       at com.onesignal.common.modeling.Model.getId(Model.java:4)
       at com.onesignal.common.modeling.ModelStore.get(ModelStore.java:24)
       at com.onesignal.common.modeling.SingletonModelStore.getModel(SingletonModelStore.java:4)
       at com.onesignal.user.internal.operations.impl.listeners.SubscriptionModelStoreListener.getUpdateOperation(SubscriptionModelStoreListener.java:37)
       at com.onesignal.user.internal.operations.impl.listeners.SubscriptionModelStoreListener.getUpdateOperation(SubscriptionModelStoreListener.java:1)
       at com.onesignal.core.internal.operations.listeners.ModelStoreListener.onModelUpdated(ModelStoreListener.java:45)
       at com.onesignal.common.modeling.ModelStore$onChanged$1.invoke(ModelStore.java:2)
       at com.onesignal.common.modeling.ModelStore$onChanged$1.invoke(ModelStore.java:1)
       at com.onesignal.common.events.EventProducer.fire(EventProducer.java:21)
       at com.onesignal.common.modeling.ModelStore.onChanged(ModelStore.java:20)
       at com.onesignal.common.modeling.Model$notifyChanged$1.invoke(Model.java:2)
       at com.onesignal.common.modeling.Model$notifyChanged$1.invoke(Model.java:1)
       at com.onesignal.common.events.EventProducer.fire(EventProducer.java:21)
       at com.onesignal.common.modeling.Model.notifyChanged(Model.java:18)
       at com.onesignal.common.modeling.Model.setOptAnyProperty(Model.java:49)
       at com.onesignal.user.internal.subscriptions.SubscriptionModel.setStatus(SubscriptionModel.java:14)
       at com.onesignal.user.internal.subscriptions.impl.SubscriptionManager.addOrUpdatePushSubscription(SubscriptionManager.java:43)
       at com.onesignal.notifications.internal.listeners.DeviceRegistrationListener$retrievePushTokenAndUpdateSubscription$1.invokeSuspend(DeviceRegistrationListener.java:70)
       at com.onesignal.notifications.internal.listeners.DeviceRegistrationListener$retrievePushTokenAndUpdateSubscription$1.invoke(DeviceRegistrationListener.java:2)
       at com.onesignal.notifications.internal.listeners.DeviceRegistrationListener$retrievePushTokenAndUpdateSubscription$1.invoke(DeviceRegistrationListener.java:1)
       at com.onesignal.common.threading.ThreadUtilsKt$suspendifyOnThread$1$1.invokeSuspend(ThreadUtils.kt:28)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(BaseContinuationImpl.java:8)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.java:105)
       at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoopImplBase.java:162)
       at kotlinx.coroutines.BlockingCoroutine.joinBlocking(BlockingCoroutine.java:98)
       at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(BuildersKt__Builders.kt:98)
       at kotlinx.coroutines.BuildersKt.runBlocking(Builders.kt:98)
       at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(BuildersKt__Builders.kt:2)
       at kotlinx.coroutines.BuildersKt.runBlocking$default(Builders.kt:2)
       at com.onesignal.common.threading.ThreadUtilsKt$suspendifyOnThread$1.invoke(ThreadUtils.kt:2)
       at com.onesignal.common.threading.ThreadUtilsKt$suspendifyOnThread$1.invoke(ThreadUtils.kt:1)
       at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Threads.kt:2)

isles1217 avatar Oct 17 '23 16:10 isles1217

Thank you all for your patience, unfortunately we are struggling to reproduce this on our end. I suspect a race condition during initialization, but I can't identify it looking through the code.

If you are able to capture any logs beyond the stack trace (preferably with OneSignal.getDebug().setLogLevel(LogLevel.VERBOSE); set), that will help us understand the sequence of events.

It might also help to understand where OneSignal.initWithContext called, if that could be provided I'd appreciate it.

brismithers avatar Oct 27 '23 12:10 brismithers

Have you ruled out that this isn't a proguard/obfuscation issue? That's the smell I'm getting from this.

isles1217 avatar Oct 27 '23 14:10 isles1217

If it's not a proguard/obfuscation problem, the simplest way to guard against initialization race conditions is to wrap relevant member variables in lazy initializers (assuming Kotlin here).

isles1217 avatar Oct 27 '23 14:10 isles1217

We haven't ruled out proguard or obfuscation as the issue, but from the stack trace and how it appears to be non-deterministic makes me feel it's tied to how we save and load state across app lifecycles. @isles1217 if you could provide a more complete log showing the initialization prior to the stack trace, or provided more context in how OneSignal is initialized within your app, that would be tremendously helpful. Thanks for the insights!

brismithers avatar Oct 30 '23 14:10 brismithers

@brismithers see this comment for initialization logic: https://github.com/OneSignal/OneSignal-Android-SDK/issues/1880#issuecomment-1787886484

isles1217 avatar Nov 03 '23 17:11 isles1217

@isles1217 thanks for that! I wonder if your two issues are linked, if initWithContext is being driven so much it might drive some funky concurrency issues. Note I have PR #1903 which synchronizes initialization, and we also released v5.0.4 which added synchronization to the very area your stack trace is surfacing (#1876). I'm curious if these resolve what you are seeing in this issue.

brismithers avatar Nov 07 '23 16:11 brismithers

This has happened again in 5.0.4

Fatal Exception: java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
       at com.onesignal.common.modeling.Model.getStringProperty(Model.kt:484)
       at com.onesignal.common.modeling.Model.getStringProperty$default(Model.kt:481)
       at com.onesignal.common.modeling.Model.getId(Model.kt:60)
       at com.onesignal.common.modeling.ModelStore.get(ModelStore.kt:73)
       at com.onesignal.common.modeling.SingletonModelStore.getModel(SingletonModelStore.kt:24)
       at com.onesignal.session.internal.influence.impl.InfluenceDataRepository.getNotificationIndirectAttributionWindow(InfluenceDataRepository.kt:138)
       at com.onesignal.session.internal.influence.impl.NotificationTracker.getIndirectAttributionWindow(NotificationTracker.kt:36)
       at com.onesignal.session.internal.influence.impl.ChannelTracker.getLastReceivedIds(ChannelTracker.kt:81)
       at com.onesignal.session.internal.influence.impl.InfluenceManager.restartSessionTrackersIfNeeded(InfluenceManager.kt:132)
       at com.onesignal.session.internal.influence.impl.InfluenceManager.onSessionStarted(InfluenceManager.kt:57)
       at com.onesignal.session.internal.session.impl.SessionService$onFocus$1.invoke(SessionService.kt:80)
       at com.onesignal.session.internal.session.impl.SessionService$onFocus$1.invoke(SessionService.kt:80)
       at com.onesignal.common.events.EventProducer.fire(EventProducer.kt:50)
       at com.onesignal.session.internal.session.impl.SessionService.onFocus(SessionService.kt:80)
       at com.onesignal.core.internal.application.impl.ApplicationService$handleFocus$1.invoke(ApplicationService.kt:369)
       at com.onesignal.core.internal.application.impl.ApplicationService$handleFocus$1.invoke(ApplicationService.kt:369)
       at com.onesignal.common.events.EventProducer.fire(EventProducer.kt:50)
       at com.onesignal.core.internal.application.impl.ApplicationService.handleFocus(ApplicationService.kt:369)
       at com.onesignal.core.internal.application.impl.ApplicationService.onActivityStarted(ApplicationService.kt:154)
       at android.app.Application.dispatchActivityStarted(Application.java:406)
       at android.app.Activity.dispatchActivityStarted(Activity.java:1264)
       at android.app.Activity.onStart(Activity.java:1747)
       at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:344)
       at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java)
       at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1432)
       at android.app.Activity.performStart(Activity.java:7892)
       at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3326)
       at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
       at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2045)
       at android.os.Handler.dispatchMessage(Handler.java:107)
       at android.os.Looper.loop(Looper.java:214)
       at android.app.ActivityThread.main(ActivityThread.java:7399)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:502)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)

fanwgwg avatar Nov 18 '23 09:11 fanwgwg

Happens also in the Flutter lib 5.0.4. This is causing crashes specifically on Android 13. Please give us some visibility on how you will tackle this problem as it is a critical bug !

ipapps avatar Nov 23 '23 08:11 ipapps

thank you for the feedback, we haven't been able to reproduce the issue on our side so we are primarily looking through code in an attempt to understand the issue. If you are able to provide a simple reproduction that will most definitely be helpful!

brismithers avatar Nov 27 '23 20:11 brismithers

I believe this is the same as issue #1995 and a fix for this is now available in OneSignal-Android-SDK 5.1.6

jkasten2 avatar Mar 01 '24 23:03 jkasten2