Showing full stacktraces

Bugsnag supports unminifying and demangling stacktraces using ProGuard files, LLVM debug symbol maps (dSYMs), and source maps to show a full stacktrace with methods, file paths, and line numbers for JavaScript and native errors.

Uploading mapping files for Android

If you enable ProGuard for your Android builds you can upload the generated mapping file using the Android Mapping Upload API to de-obfuscate the native Android stack traces.

Uploading debug symbol maps (dSYMs) for iOS

You can upload dSYM files using the dSYM Upload API to symbolicate native iOS stack traces.

Uploading source maps

Source maps can be uploaded to Bugsnag to unminify JavaScript stack traces. To ensure all builds are correctly mapped, you will need to generate and upload source maps for Android and iOS if you support both platforms.

Generating source maps

Source maps can be generated using the react-native bundle command.

Debug variant

The source maps used for the debug variant can be generated via the React Native bundler using the --dev true option. Debug variant bundle files are not minified.

iOS example:

$ react-native bundle \
    --platform ios \
    --dev true \
    --entry-file index.ios.js \
    --bundle-output ios-debug.bundle \
    --sourcemap-output ios-debug.bundle.map

Android example:

$ react-native bundle \
    --platform android \
    --dev true \
    --entry-file index.android.js \
    --bundle-output android-debug.bundle \
    --sourcemap-output android-debug.bundle.map

Release variant

The source maps used for the release variant can be generated via the React Native bundler using the --dev false option. Release variant bundle files are minified.

iOS example:

$ react-native bundle \
    --platform ios \
    --dev false \
    --entry-file index.ios.js \
    --bundle-output ios-release.bundle \
    --sourcemap-output ios-release.bundle.map

Android example:

$ react-native bundle \
    --platform android \
    --dev false \
    --entry-file index.android.js \
    --bundle-output android-release.bundle \
    --sourcemap-output android-release.bundle.map

Uploading source maps to Bugsnag

The generated source map and bundle file can be uploaded using the bugsnag-sourcemaps command-line tool. Install the package using npm or yarn:

$ npm install -g bugsnag-sourcemaps

To upload your source map files, run the bugsnag-sourcemaps command including at least the following required fields:

Name Option Description
API key --api-key Your API key, available on the Bugsnag dashboard in Project Settings
App version --app-version or --code-bundle-id The version of the your application which was used to generate the source map
Bundle --minified-file The path to bundle output file generated by react-native bundle
Source map --source-map The path to the source map output file generated by react-native bundle
Minified URL --minified-url The location of the JavaScript bundle as reported in a stack trace

A list of all options is available using the --help flag.

Debug variant example

on iOS:

$ bugsnag-sourcemaps upload \
    --api-key YOUR_API_KEY_HERE \
    --app-version 1.0.0 \
    --minified-file ios-debug.bundle \
    --source-map ios-debug.bundle.map \
    --minified-url "http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false"

on Android:

$ bugsnag-sourcemaps upload \
    --api-key YOUR_API_KEY_HERE \
    --app-version 1.0.0 \
    --minified-file android-debug.bundle \
    --source-map android-debug.bundle.map \
    --minified-url "http://10.0.2.2:8081/index.android.bundle?platform=android&dev=true&minify=false"

Release variant example

Since the release variant of React Native source maps does not include the source files used to generate the map, add the --upload-sources flag to upload source files and show code snippets within stacktraces on the Bugsnag dashboard.

iOS example:

$ bugsnag-sourcemaps upload \
    --api-key YOUR_API_KEY_HERE \
    --app-version 1.0.0 \
    --minified-file ios-release.bundle \
    --source-map ios-release.bundle.map \
    --minified-url main.jsbundle \
    --upload-sources

Android example:

$ bugsnag-sourcemaps upload \
    --api-key YOUR_API_KEY_HERE \
    --app-version 1.0.0 \
    --minified-file android-release.bundle \
    --source-map android-release.bundle.map \
    --minified-url index.android.bundle \
    --upload-sources

Selecting an app version

The app version argument (--app-version) should be the version of your app used to generate the source map. If unspecified, the value is populated from the version field of your project’s package.json. To check which app version is being used, check the version and versionCode values which appear in error reports on the “App” tab.

If this value differs from the version you wish to use, you can change the version as a part of your Bugsnag client configuration:

import { Client, Configuration } from 'bugsnag-react-native';

const config = new Configuration('your-API-key');
config.appVersion = require('./package.json').version;
const bugsnag = new Client(config);

See the appVersion configuration option documentation for more information.

To instead update the native components’ version fields, update the following values:

  • For iOS apps the app version is taken from the Version Number setting and the versionCode is taken from the Build Number setting. See the iOS developer documentation in Version Numbers and Build Numbers for more information.
  • For Android apps the app version is taken from the versionName setting and the versionCode is taken from the versionCode setting. See the Android developer documentation on how to Version Your App for more information.

Working with Code Push

If you are using a tool such as Code Push to push JavaScript updates to your React Native app without changing the binary, a single app version applies to multiple JavaScript bundles. In order to get unminified JavaScript stack traces, you will need to use a code bundle identifier (--code-bundle-id) instead of the --app-version argument. During each deploy, complete the following steps:

  1. Define and set a code bundle identifier in your Bugsnag configuration before each release. This identifier can be any string as long as it matches what is sent to the source map upload API in step 3.

    const config = new Configuration('YOUR_API_KEY_HERE');
    config.codeBundleId = '1.0.0-b12'
    const bugsnag = new Client(config);
    
  2. Release your app using Code Push, specifying the --outputDir in order to capture the source map and asset bundle files for upload in step 3.

    $ code-push release-react APP_NAME \
        <platform> \ # "ios" or "android"
        --outputDir build <other options>
    
  3. Upload the source map, specify the code bundle identifier in the source map upload instead of the app version field and using --add-wildcard-prefix to allow wildcard matching of file paths avoiding the UUIDs generated by Code Push.

    on iOS:

    $ bugsnag-sourcemaps upload \
        --api-key YOUR_API_KEY_HERE \
        --code-bundle-id 1.0.0-b12 \
        --source-map build/main.jsbundle.map \
        --minified-file build/main.jsbundle \
        --minified-url main.jsbundle \
        --upload-sources \
        --add-wildcard-prefix
    

    on Android:

    $ bugsnag-sourcemaps upload \
        --api-key YOUR_API_KEY_HERE \
        --code-bundle-id 1.0.0-b12 \
        --source-map build/index.android.bundle.map \
        --minified-file build/index.android.bundle \
        --minified-url index.android.bundle \
        --upload-sources \
        --add-wildcard-prefix
    
  4. Repeat steps 2 and 3 for iOS or Android if you support both platforms.

When a React Native error event is received with a code bundle identifier in the app data, we will attempt to find an uploaded source map for the URL/file in the stacktrace and a matching identifier. This overrides the normal behaviour that looks up uploaded source maps based on URL, file, and app version.

Selecting a minified URL

The --minified-url field should be the location of the bundle file as reported in the stacktrace. Asterisks can be used as a wildcard.

React Native reports the location in the stacktrace in different ways depending on the platform and variant.

iOS minified URL naming

For debug (dev) variants the location is the locally hosted bundler location, which is usually:

http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false

For release variants the location is main.jsbundle.

Android minified URL naming

For debug (dev) variants the location is the locally hosted bundler location, which should be similar to:

http://10.0.2.2:8081/index.android.bundle?platform=android&dev=true&minify=false

For release variants the location is index.android.bundle.

Using wildcards

The asterisk character can be used as a wildcard for the minified URL field and source file field names. This adds flexibility when matching a source map against an error report and allows source files to be referenced without the full path to the file.

Multiple wildcards can be used in the same field. Each asterisk matches zero or more characters.

To allow the path to the source files to be matched without the file path (making it more flexible matching against bundles generated on different machines), run bugsnag-sourcemaps with the --add-wildcard-prefix option:

$ bugsnag-sourcemaps upload \
    --api-key YOUR_API_KEY_HERE \
    --app-version 1.0.0 \
    --source-map ios-release.bundle.map \
    --minified-file ios-release.bundle \
    --minified-url main.jsbundle \
    --upload-sources \
    --add-wildcard-prefix # <--

Wildcard matching caveats

If multiple minified URLs in source map uploads match the same minified URL/file and app version in an error report (due to the use of wildcards) the most recently uploaded source map matching the URL/file and app version will be used on the error.

If multiple source files in an upload match against a source file path (due to the use of wildcards) the selection of source file will be arbitrary.

Care should be taken to avoid a wildcarded minified URL matching both debug and release variants as the bundle and source map file for those variants differ and can result in incorrect mappings.

Overwriting existing source maps

If an uploaded source map is out of date or otherwise incorrect, it can be overwritten with a new source map by uploading with the --overwrite flag.

An overwritten source map cannot be recovered.

Frequently asked questions

Why isn’t the uploaded source map getting applied to my error?

A source map is applied to a frame in a stack trace of an error by matching:

  • the app version uploaded with the source map to the version of the app generating the error and
  • the name of the bundle file uploaded with the source map to the URL or file in the stack frame

If the uploaded source map is not being applied correctly, you should verify that:

  • The error event was received after the source map was uploaded
  • The --minified-url field specified during upload matches the URL or file in the stack frame. It must match exactly unless wildcard logic has been used.
  • The --app-version field matches the “version” or the “versionCode” app metadata as seen in the app tab of the error on Bugsnag
  • The bundle file was uploaded in the --minified-file field

Why can’t I see the code context for my mapped JavaScript error?

Bugsnag needs visibility of the source code to display the code context with a stacktrace.

When using react-native bundle with --dev true, it includes the the contents of the source files in the sourcesContent field of the source map.

When using the bundler with --dev false, it does not include source file contents in the source map. In this case, use the --upload-sources option in bugsnag-sourcemaps to upload all files referenced by the source map.

Where can I see the details of the source maps that I’ve uploaded?

You can see details of the source maps that you’ve uploaded by going to Project Settings -> Uploaded source maps.

Do the uploaded source maps get applied retroactively to existing errors?

Once a source map is uploaded it will only get applied to new error events. It does not get applied retroactively to existing errors events.

Why is my mapped stacktrace showing the wrong line of code?

If the stacktrace has been mapped but is pointing to the wrong line of code, it’s often due to the wrong bundle/source map file being uploaded for the URL/file in the reported stacktrace.

The most common cause of misaligned source files is uploading a bundle for a release build (set with --minified-file) with a minified URL for a debug build (set with --minified-url). In this case, the source files correspond to the release bundle but the line numbers correspond to the debug bundle.

See Generating source maps for guidance of how to generate the correct source map for the build variant.