Showing full stacktraces

Bugsnag supports unminifying and demangling stacktraces using ProGuard/Jack 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 or use the Jack toolchain 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 de-obfuscate JavaScript stack traces.

Generating source maps

Source maps are automatically created when using the JavaScript bundler for React Native on a simulator or can be generated using the react-native bundle command.

When running the debug (dev) variant the generated bundle file isn’t normally minified whereas for the release variant (and other non-dev variants) it is. The source maps for each vary accordingly.

Debug variant

The source maps used for the debug variant can be generated via the react native bundler using the --dev true option.

$ react-native bundle \
  --platform ios \
  --dev true \
  --entry-file index.ios.js \
  --bundle-output <path_to_dev_bundle> \
  --sourcemap-output <path_to_dev_source_map>

Alternatively, if you’re using the React Native bundler you can grab the files that it has generated.

$ curl "http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false" > \
  <path_to_dev_bundle>

$ curl "http://localhost:8081/index.ios.bundle.map?platform=ios&dev=true&minify=false" > \
  <path_to_dev_source_map>

Release variant

The source maps used for the release variant (or other non-dev variants) can be generated via the react native bundler using the --dev false option.

$ react-native bundle \
  --platform ios \
  --dev false \
  --entry-file index.ios.js \
  --bundle-output <path_to_bundle> \
  --sourcemap-output <path_to_dev_source_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@1.0.0-rc.5

Run the bugsnag-sourcemaps command as described below from the root of your project. A list of all options is available using the --help flag.

Debug variant example

$ bugsnag-sourcemaps upload \
     --api-key <project API key> \
     --source-map <path to source map> \
     --strip-project-root \
     --minified-file <path to bundle> \
     --minified-url http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false

Release variant example

Add the --upload-sources flag to upload source files and show code within stacktraces on the Bugsnag dashboard.

$ bugsnag-sourcemaps upload \
     --api-key <PROJECT API KEY> \
     --source-map <path to source map> \
     --strip-project-root \
     --minified-file <path to bundle> \
     --minified-url main.jsbundle \
     --upload-sources

Frequently asked questions

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

Source maps get applied to an error based on the url/file in the stacktrace and the version of the app. The bundle file also needs to be uploaded to ensure that mapping and grouping work correctly.

If the uploaded source map isn’t getting applied correctly you should check the following:

  • The --minified-url field specified during upload matches the url/file in the stacktrace. It must exactly match if wildcards haven’t been used or match according to the wildcard logic if they have been used.
  • The --app-version field either matches the app version or the app versionCode (as seen in the app tab on the error)
  • The bundle file was uploaded in the --minified-file field
  • The error event was received after the source map was uploaded

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

Bugsnag needs visibility of the source code in order to display the code context against the lines in the stacktrace. This can either be achieved by ensuring that the sourcesContent field in the source map file is populated correctly in the source map or by uploading the required source files during source map upload.

When using the debug variant of the react-native bundle CLI it applies the sourceContent to the source map. However it doesn’t populate the field with the full source content for the release variant.

Use the --upload-sources flag in bugsnag-sourcemaps to upload all files referenced by the source map.

Why am I getting a response of “Nothing to upload” when uploading my source map?

A 422 (Unprocessable Entity) status code is returned with a message of “Nothing to upload” if the files haven’t been uploaded correctly when using cURL.

This is often due to missing the @ symbol before the file path for the source map file when using cURL. If the @ symbol is omitted the path to the file is sent rather than the file itself.

What app version should be used during source map upload?

The app version argument (--app-version) should be the version of the app that the source map applies to. If unspecified, the value is populated from the version field of your project’s package.json. To check what 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.

If you’re using a tool such as CodePush to push JavaScript updates without changing the binary you will need to use a code bundle identifier instead of the --app-version (since the same app version can apply to different JavaScript bundles).

What should I set the minified url to during source map upload?

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

For debug (dev) variants the location is normally the locally hosted bundler location (e.g. http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false)

For release (and other non-dev) variants the location is normally main.jsbundle.

Android

For debug (dev) variants the location is normally the locally hosted bundler location (e.g. http://10.0.2.2:8081/index.android.bundle?platform=android&dev=true&minify=false)

For release (and other non-dev) variants the location is normally index.android.bundle.

Do you support partial matching/wildcards for the minified URL?

Yes! 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 <PROJECT API KEY> \
     --source-map <path to source map> \
     --strip-project-root \
     --add-wildcard-prefix \ # <--
     --minified-file <path to bundle> \
     --minified-url main.jsbundle \
     --upload-sources

An example of the same behavior using cURL:

$ curl https://upload.bugsnag.com/ \
  -F apiKey=YOUR_API_KEY_HERE \
  -F appVersion=1.0 \
  -F minifiedUrl="main.jsbundle" \
  -F sourceMap=@path/to/main.jsbundle.map \
  -F minifiedFile=@path/to/main.jsbundle \
  -F overwrite=true
  -F */index.ios.js=@/workspace/app/index.ios.js
  # ... plus all other source files

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.

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.

How should I upload source maps if I’m using CodePush?

If you’re using a tool such as CodePush to push JavaScript updates to your React Native app without changing the app binary you will need to do the following to get de-obfuscated JavaScript stacktraces:

  1. Define and set a code bundle identifier before your deploy in your Bugsnag configuration. 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-123'
    const bugsnag = new Client(config);
    
  2. Release your app using CodePush, specifying the --sourcemapOutput or --outputDir in order to capture the source map and asset bundle files for upload in step 3.

    $ code-push release-react <appName> <platform> \
      --outputDir <outputDir> <other options>
    
  3. Specify the code bundle identifier in the source map upload instead of the app version field.

    $ bugsnag-sourcemaps upload \
         --api-key <PROJECT API KEY> \
         --code-bundle-id 1.0-123 \
         --source-map <path to source map> \
         --minified-file <path to bundle> \
         --upload-sources \
         --add-wildcard-prefix
    

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.

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 this is uploading minified files (generated for non-dev variants) against the development version of the minified URL (set with --minified-url) where the stacktrace refers to line numbers in the non-minified bundle file.

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