- Published on
React Native - Understanding Obfuscated Unhandled Exception in Crashlytics
- Authors
- Name
- Galih Laras Prakoso
- @galihlprakoso
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:
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.