react-native: Android TransactionTooLargeException

Environment

Environment: OS: macOS High Sierra 10.13.4 Node: 10.2.1 Yarn: 1.7.0 npm: 5.6.0 Watchman: 4.9.0 Xcode: Xcode 9.3.1 Build version 9E501 Android Studio: 3.1 AI-173.4720617

Packages: (wanted => installed) react: 16.4.0 => 16.4.0 react-native: ^0.55.4 => 0.55.4

Steps to Reproduce

I was unable to find reproduction steps for this error. I’m using crashlytics to collect informations about app crashes, that’s how I found out about this one.

I’m also aware about https://github.com/facebook/react-native/issues/15429, and did updated compileSdkVersion and targetSdkVersion to 26, then to 27 and still see this exception reported.

For the latest version it mainly happens on Android 7 and 8 and Samsung and Motorola devices.

Here is a thread dump for one particular instance: org.luksza.habitchallenge_issue_14_crash_5B08A3070387000105A3FE70635B0C4C_DNE_1_v2.txt

Expected Behavior

Application should not crash.

Actual Behavior

Application crashes

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 33
  • Comments: 38 (2 by maintainers)

Commits related to this issue

Most upvoted comments

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.

Still an issue!

Also another note: most React Native apps don’t heavily depend on the saved instance state for restarting, so I believe (we’re testing this right now) it should be safe to just clear the bundle if it’s too large. This is what we’re trying to add to MainActivity:

    /**
     * Added to not save instance state when the state is too large. When the
     * parcel is too large, a crash occurs in the form of the ones at
     * https://github.com/facebook/react-native/issues/19458
     *
     * This usually happens because the Android activity saves the information
     * for the entire window hierarchy. This can get really large if there are
     * a ton of views in a FlatList:
     * https://android.googlesource.com/platform/frameworks/base/+/808b9f1b730ed7d046c26d0c11181632379ce570/core/java/android/app/Activity.java#2275
     *
     * While this crash actually doesn't affect the functioning of the app, I
     * think it may still affect our Android crash rate stats since it shows
     * up in the Google Play Developer Console. High crash rates lower our
     * Google Play Store ranking.
     *
     * Not saving state should be fine for the user too. We don't rely on
     * instance state for the state of our app, as everything is stored using
     * AsyncStorage inside of JS code instead.
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        try {
            super.onSaveInstanceState(outState);
            Parcel parcel = Parcel.obtain();
            int size;

            parcel.writeBundle(outState);
            size = parcel.dataSize();

            // This was determined by looking at Bugsnag errors like:
            // "java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 529044 bytes"
            //
            // There were no errors for parcels with size < 520000 and many
            // above. As such, we limit the parcel size to 500000 to have a bit
            // of leeway.
            int maximumParcelSize = 500000;
            if (size > maximumParcelSize) {
                outState.clear();
            }

            parcel.recycle();
        } catch (Exception e) {
            // Failed saves don't hurt anyone, so we just swallow the errors
            // Alternatively log a handled error
        }
    }
}

Unfortunately, the issue is still there in RN 0.63.2. Is there anyone managed to fix it?

Having the same issue on rn 0.62.2

I still have this problem with react-native 61.5. Google’s Crashalytics show the following:

Caused by android.os.TransactionTooLargeException
data parcel size 402196 bytes
---
android.os.BinderProxy.transactNative (Binder.java)
android.os.BinderProxy.transact (Binder.java:1142)
android.app.IActivityManager$Stub$Proxy.activityStopped (IActivityManager.java:3890)
android.app.servertransaction.PendingTransactionActions$StopInfo.run (PendingTransactionActions.java:144)
android.os.Handler.handleCallback (Handler.java:873)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loop (Looper.java:214)
android.app.ActivityThread.main (ActivityThread.java:6986)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1445)

My only package that would write data is Firebase, maybe this is the culprit?

Any updates on this issue? We’re having many cases in our app, and our bug reports all point to this happening when the user puts the app on the background (Always happens after a sequence of onPause, onSaveInstanceState, onStop). These reports alone is causing the majority of our crashes and the crash rate increased significantly due to it.

@fossage Sure, but even under normal circumstances you might use the tool to see if there is something suspicious going on : too much data saved in the views, data placed in the Bundle from an unsuspecting source, etc. It’s very likely that something is saving a small amount of data all the time and under certain conditions that small amount of data passes the limit to trigger a TransactionTooLargeException.

Just as a general example : an Android app might implement a ViewPager with a FragmentStatePagerAdapter. Under normal circumstances, each Fragment will result in a small amount of data getting saved in onSaveInstanceState of the overall Activity. If you happen to have dozens and dozens of them, though, this accumulated data could trigger a TransactionTooLargeException. Something could be happening here with Views.

We still see this issue as of with React Native 59.9

The problem is caused by saving too much state in onSaveInstanceState. For details see here. Where is all the saved state coming from? Is it being saved by the views? You can use something like TooLargeTool to debug this. If it’s being saved the Activities or Fragments you can use Bridge to get around it. If it’s all in the views themselves, that’s a bit trickier. (Bridge doesn’t currently support saving state for views, but we’re looking into it.)