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

Update NavKey.kt to handle null id #717

Open
wants to merge 1 commit into
base: 1.x
Choose a base branch
from

Conversation

ToshioMagic
Copy link

Description

Uses java.util.Objects.hashCode() to protect the NavKey.hashCode function from throwing errors when id is null. Id is never supposed to be null, but we keep getting crashing errors in our app in prod that we can't reproduce.

Here's the stacktrace from our app:

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.hashCode()' on a null object reference
        at com.bumble.appyx.core.navigation.NavKey.hashCode(NavKey.kt:35)
        at java.lang.Object.toString(Object.java:299)
        at java.lang.String.valueOf(String.java:4092)
        at java.lang.StringBuilder.append(StringBuilder.java:179)
        at android.os.Parcel.readValue(Parcel.java:4405)
        at android.os.Parcel.readMapInternal(Parcel.java:5319)
        at android.os.Parcel.readHashMapInternal(Parcel.java:5304)
        at android.os.Parcel.readValue(Parcel.java:4629)
        at android.os.Parcel.readValue(Parcel.java:4402)
        at android.os.Parcel.readListInternal(Parcel.java:5411)
        at android.os.Parcel.readArrayListInternal(Parcel.java:5430)
        at android.os.Parcel.readValue(Parcel.java:4663)
        at android.os.Parcel.readValue(Parcel.java:4402)
        at android.os.Parcel.readValue(Parcel.java:4387)
        at androidx.compose.runtime.ParcelableSnapshotMutableState$Companion$CREATOR$1.createFromParcel(ParcelableSnapshotMutableState.android.kt:60)
        at androidx.compose.runtime.ParcelableSnapshotMutableState$Companion$CREATOR$1.createFromParcel(ParcelableSnapshotMutableState.android.kt:55)
        at android.os.Parcel.readParcelableInternal(Parcel.java:4880)
        at android.os.Parcel.readValue(Parcel.java:4633)
        at android.os.Parcel.readValue(Parcel.java:4402)
        at android.os.Parcel.readListInternal(Parcel.java:5411)
        at android.os.Parcel.readArrayListInternal(Parcel.java:5430)
        at android.os.Parcel.readValue(Parcel.java:4663)
        at android.os.Parcel.readValue(Parcel.java:4402)
        at android.os.Parcel.readMapInternal(Parcel.java:5320)
        at android.os.Parcel.readHashMapInternal(Parcel.java:5304)
        at android.os.Parcel.readValue(Parcel.java:4629)
        at android.os.Parcel.readValue(Parcel.java:4402)
        at android.os.Parcel.readMapInternal(Parcel.java:5320)
        at android.os.Parcel.readHashMapInternal(Parcel.java:5304)
        at android.os.Parcel.readValue(Parcel.java:4629)
        at android.os.Parcel.readValue(Parcel.java:4402)
        at android.os.Parcel.readListInternal(Parcel.java:5411)
        at android.os.Parcel.readArrayListInternal(Parcel.java:5430)
        at android.os.Parcel.readValue(Parcel.java:4663)
        at android.os.Parcel.readValue(Parcel.java:4402)
        at android.os.Parcel.-$$Nest$mreadValue(Unknown)
        at android.os.Parcel$LazyValue.apply(Parcel.java:4500)
        at android.os.Parcel$LazyValue.apply(Parcel.java:4459)
        at android.os.BaseBundle.unwrapLazyValueFromMapLocked(BaseBundle.java:415)
        at android.os.BaseBundle.getValueAt(BaseBundle.java:401)
        at android.os.BaseBundle.getValue(BaseBundle.java:381)
        at android.os.BaseBundle.getValue(BaseBundle.java:364)
        at android.os.BaseBundle.getValue(BaseBundle.java:357)
        at android.os.Bundle.getParcelableArrayList(Bundle.java:1046)
        at androidx.compose.ui.platform.DisposableSaveableStateRegistry_androidKt.toMap(DisposableSaveableStateRegistry.android.kt:173)
        at androidx.compose.ui.platform.DisposableSaveableStateRegistry_androidKt.DisposableSaveableStateRegistry(DisposableSaveableStateRegistry.android.kt:76)
        at androidx.compose.ui.platform.DisposableSaveableStateRegistry_androidKt.DisposableSaveableStateRegistry(DisposableSaveableStateRegistry.android.kt:54)
        at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:109)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:155)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:154)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:401)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:154)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:133)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:97)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3593)
        at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3520)
        at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:743)
        at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1114)
        at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:649)
        at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:635)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:124)
        at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1625)
        at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:124)
        at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:180)
        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:320)
        at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:198)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:124)
        at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1706)
        at android.view.View.dispatchAttachedToWindow(View.java:23227)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3698)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3705)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3705)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3705)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3705)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3705)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3705)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3901)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3288)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:11344)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1689)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1698)
        at android.view.Choreographer.doCallbacks(Choreographer.java:1153)
        at android.view.Choreographer.doFrame(Choreographer.java:1079)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1646)
        at android.os.Handler.handleCallback(Handler.java:958)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        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(Method.java:-2)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)

Check list

  • I have updated CHANGELOG.md if required.
  • I have updated documentation if required.

Uses java.util.Objects.hashCode() to protect the NavKey.hashCode function from throwing errors when id is null. Id is never supposed to be null, but we keep getting crashing errors in our app in prod that we can't reproduce.
@ToshioMagic
Copy link
Author

When should I expect a review?

@LachlanMcKee
Copy link
Collaborator

Hi @ToshioMagic

That's very strange they the id is throwing a npe. Is it possible that you have removed kotlin intrinsics via r8? (As described here https://www.guardsquare.com/blog/eliminating-data-leaks-caused-by-kotlin-assertions)

@ToshioMagic
Copy link
Author

We're using proguard, not R8. And our proguard is pretty vanilla.


-dontwarn {{redacted}}
-dontwarn {{redacted}}
-dontwarn {{redacted}}
-dontobfuscate

-keep class {{redacted}}

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

Successfully merging this pull request may close these issues.

2 participants