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.

Source maps are automatically created when using the React Native Packager on a simulator or can be generated using the react-native bundle cli.

Once generated the Source Map Upload API can be used to upload the source map and bundle file. The use of this varies depending on the build variant and platform.

The upload API should be used as follows for React Native source maps:

  • apiKey - the Bugsnag API key that is used in your app.
  • appVersion - the version of the Android or iOS app that the source map applies to. This can either be the app version or versionCode. See here for more details.
    Note If you’re using a tool such as CodePush to push JavaScript updates you should use codeBundleId instead of appVersion. See here for details.
  • minifiedUrl - the location of the bundle file as reported in the stacktrace. For debug builds this is usually the locally hosted packager location (e.g. http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false). For release builds this is usually just the name of the bundle file (e.g. main.jsbundle). Asterisks can be used as a wildcard.
  • sourceMap - the source map file.
  • minifiedFile - the bundle file.
  • overwrite (optional) - specifies whether to overwrite any existing version of the files for this minified url and app version. Defaults to false.
  • <sources> (optional) - each source file referenced by the source map (if the source hasn’t been included in the sourcesContent field of the source map). Each field name should be the full path of the source file as referenced in the sources section of the source map. Asterisks in the field name can be used as a wildcard.

Debug variant example

$ curl https://upload.bugsnag.com/ \
  -F apiKey=YOUR_API_KEY_HERE \
  -F appVersion=1.0 \
  -F minifiedUrl="http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false" \
  -F sourceMap=@path/to/index.ios.bundle.map \
  -F minifiedFile=@path/to/index.ios.bundle \
  -F overwrite=true

Release variant example

$ 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 /workspace/app/index.ios.js=@/workspace/app/index.ios.js

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 minifiedUrl 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 appVersion 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 minifiedFile 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 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.

The source files can be uploaded to Bugsnag if the sourcesContent is not populated properly in the source map. This can be done for each source file during source map upload by specifiying the full path to the source file (as it appears in the mapped stacktrace) as the field name and the file as the value (as shown in the release variant example).

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.

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 appVersion field should be the version of the app that the source map applies to. This should match either the version or the versionCode field as it appears in the error report (as seen in the app tab of the error).

The app version and versionCode that appear for the error reports vary depending on the platform:

  • For iOS apps the app version is taken from the Version Number setting and the versionCode is taken from the Build Number setting. See here for details of the different iOS version settings.
  • For Android apps the app version is taken from the versionName setting and the versionCode is taken from the versionCode setting. See here for details of the different Android version settings.

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

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 retrospectively to existing errors?

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

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

The asterisk character can be used as a wildcard for the minifiedUrl 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.

e.g. To allow the path to the source file index.ios.js to be matched without the file path (making it more flexible matching against bundles generated on different machines) the following curl command could be used:

$ 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

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.

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 codeBundleId in the source map upload instead of the appVersion field.

    $ curl https://upload.bugsnag.com/ \
      -F apiKey=YOUR_API_KEY_HERE \
      -F codeBundleId=1.0-123 \
      -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
    

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