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

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

Closed
1 task done
fanwgwg opened this issue Sep 15, 2023 · 14 comments
Closed
1 task done
Labels

Comments

@fanwgwg
Copy link

fanwgwg commented Sep 15, 2023

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

  • I agree to follow this project's Code of Conduct
@fanwgwg fanwgwg changed the title [Bug]: Random crash from OneSignal at app start due to NullPointerException [Bug]: Model.getStringProperty$default crash due to NullPointerException Sep 25, 2023
@jennantilla
Copy link
Contributor

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!

@fanwgwg
Copy link
Author

fanwgwg commented Sep 28, 2023

@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.

@dmytroreutov
Copy link

dmytroreutov commented Oct 3, 2023

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)

@isles1217
Copy link

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)

@brismithers
Copy link
Contributor

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 brismithers self-assigned this Oct 27, 2023
@isles1217
Copy link

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

@isles1217
Copy link

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).

@brismithers
Copy link
Contributor

brismithers commented Oct 30, 2023

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!

@isles1217
Copy link

@brismithers see this comment for initialization logic: #1880 (comment)

@brismithers
Copy link
Contributor

@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.

@fanwgwg
Copy link
Author

fanwgwg commented Nov 18, 2023

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)

@ipapps
Copy link

ipapps commented Nov 23, 2023

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 !

@brismithers
Copy link
Contributor

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!

@jkasten2
Copy link
Member

jkasten2 commented Mar 1, 2024

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

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

No branches or pull requests

7 participants