Published on

React Native - Understanding Obfuscated Unhandled Exception in Crashlytics

Authors
stress

The story begin when my Networth app was released to production. I'm fully relying on Crashlytics on tracking any errors that happen in production. I was very confident that time because I believe that any errors that would be happening in production would be recorded in Crashlytics.

And yes! 🙂 all of the errors are recorded, but sometimes the tracked error cannot be understandable by humans, because the error stack traces on the javascript side would be hardly obfuscated. 😭 Like this:

react-native-crashlytics-error

What the heck is that?

As you can see there, the stack traces would start on the main error, in my case Fatal Exception: com.facebook.react.common.JavascriptException: TypeError: Cannot read property 'key' of undefined and it will continue to describe the exact location of the error: `There error is located at: in h -> in RCTView -> in Unknown -> in Unknown -> and so on.

Those are minified component and function names and bytecode offsets that we will never understand. This is known as symbolication.

How to understand that symbolicated information?

After some googling, finally, I found a very useful tool that will help us to understand that error. Maybe some of you have been looking for this tool or method to solve this problem and can't find any. But now, here it is.

The tool is a package called metro-symbolicate. This package is installed by default in the React Native template project. With this tool, we can symbolicate minified function names and bytecode by passing generated source map and the stack trace to metro-symbolicate via terminal.

Let's practice!

I will just use the real crash record from my Networth app's error stack traces that happened on the android platform. Okay, so first, let's put the stack traces on a file inside our React Native project called stack-traces.txt.

Fatal Exception: com.facebook.react.common.JavascriptException: TypeError: Cannot read property 'key' of undefined

This error is located at:
    in h
    in RCTView
    in Unknown
    in Unknown
    in RCTView
    in Unknown
    in RCTScrollView
    in z
    in ScrollView
...

And then we just need to run the metro-symbolicate package via npx like this:

npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map < stack-traces.txt

This command will symbolicate the error and it will look like this:

...
 in RCTView
    in C, js engine: hermes, stack:
/.../InputRecurrence.js:105:InputRecurrence
/.../node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:6871:flushPassiveEffectsImpl
...

Boom!

Every single line will be understandable now. In my case, the error happened in InputRecurrence.js:105 file. 👏🏻

There is a posibility that multiple source maps will be generated during the build process, make sure you used the one in the location described above android/app/build/generated/sourcemaps/react/release/. And also make sure that that source map you used is the latest one before you push the changes on the production build.