Inspect React Native App Crash with Source Map

Wade Huang
5 min readDec 4, 2020

--

App in Release build is minified and compiled. Crash reports won’t include the original file info as Debug build. However, most programming languages have some mechanisms to solve the problem. For example, dSYM on iOS and React Native uses Javascript Source Map which is a JSON file that contains information between the compiled file and the original files. Therefore, we can use it to find where cause crashes easier.

A crash report of a react native app on New Relic

The above image is a crash report of a react native app on New Relic which is not really readable. However, it contains some useful information such as

  • call .map() on an undefined object
  • the last stack is in line 1856 and column 3113
the useful information

Nevertheless, the two pieces of information are still too vague to find where is the crash since .map() can be used more than a hundred times in a project and line 1856 and column 3113 is a kind of magic number.

A Primitive Approach

Actually, line 1856 and column 3113 is the crash that happened in the minified and compiled file. We can unzip the apk or ipa file, you can find the minified and compiled file in these places.

  • for iOS, it is on Payload/[App Name].app/main.jsbundle of ipa
  • for Android, it is on assets/index.android.bundle of apk

Open the file and go to the line and copy the line. In the file, each line is a minified and compiled code of a javascript file. Create a new js file, paste the line, and format it, we can at least get more information about the crash.

Source Map Approach

By default, React Native has different behaviors of generating source map for iOS and Android.

  • for iOS, React Native won’t generate the source map(at least I cannot find it).
  • for Android, it is on ./android/app/build/generated/sourcemaps/react/[variant]/index.android.bundle.map

You can pass --sourcemap-output to change the output path. If your project uses CI/CD to build and distribute the app, it is recommended to include the source map files to artifacts because the source map of each build will be different, we cannot use a source map of A build for the app of B build.

  • for iOS, go to build phases in Xcode on “Bundle React Native code and images” and add the following line shown as the below image. The source map will be output on ./main.jsbundle.map
export EXTRA_PACKAGER_ARGS="--sourcemap-output main.jsbundle.map"
Set the source map output in Xcode
  • for Andorid, add the following line inside project.ext.react in./android/app/build.gradle shown as the below image. The source map will be output on ./android/app/build/index.android.bundle.map
extraPackagerArgs: ["--sourcemap-output", file("$buildDir/index.android.bundle.map")]
Set the source map output in Android Studio

However, the output path is for the demo purpose, you should change to the right place for your needs, for example the folder for CI/CD upload.

Source Map Lookup

I cannot find a GUI tool that can load the source map of react native successfully. Eventually, I created a very simple source-map-lookup library to wrap mozilla/source-map. Use this command to install source-map-lookup.

npm install -g https://github.com/weironghuang31/source-map-lookup

Then you can run this command to find the crash place of the original file.

source-map-lookup $filepath:$line:$column

Demo

In order to make a better interpretation, I created a demo app to show you the process.

  1. Create a demo app and add CrashButton.js which will cause a crash when you click the button.
The code of CrashButton

2. Run .\gradlew installRelease to build an Release app and install it on an android device.

Build an install the Release App

3. Click the button to cause crash and find the crash on logcat. And know the crash is taking place at line 415 and column 189.

The crash in logcat in Anroid Studio

4. Try the primivite approach, open the index.android.bundle, go to line 415, copy the line, paste it on a new file and format it. Although, it is still not easy to figure out which file, but we have a clue that a file includes “Touch me”.

The formatted code of line 415

5. Try source-map-lookup with the source map and the line and the column of the crash in a terminal. Then source-map-lookup prints the original file path, line and column.

Run the command in a terminal in VS code
Ctrl + click the link. Boom! VS Code navigated to the place of the crash

This my approach of inspecting react native crash. There might be a better method, however, the approach really helps me a lot. I hope it can help you as well.

References

Path Problem

You might need to use — sourcemap-use-absolute-path or — sourcemap-sources-root parameters if the build machine is not your local machine.

--

--

Wade Huang
Wade Huang

Written by Wade Huang

Expert at .Net, Nodejs, Android, React and React Native

Responses (1)