Skip to content

Uploading Symbols

Shorebird uses a fork of Flutter to build your app. This means Shorebird has built its own copy of Flutter’s engine, which means that the symbols included in the Flutter.framework or libflutter.so are slightly different from the upstream Flutter engine.

To see C++ symbols from Shorebird’s fork of Flutter’s engine in your crash reports, upload the symbols to your crash reporting tool.

Google provides instructions for how to integrate various crash reporting tools into your Flutter app:

https://docs.flutter.dev/cookbook/maintenance/error-reporting

For iOS and macOS releases, the “Artifacts” tab of the release page in Shorebird’s console links to the Flutter engine’s dSYM, next to your release’s build artifacts. To see this tab, you need the Developer role or higher, either in the organization or as a collaborator on the app. The console doesn’t link to Android engine symbols. Use the download URLs instead.

The current URL format for this tab is:

https://console.shorebird.dev/orgs/<org-id>/apps/<app-id>/releases/<release-id>/artifacts

Manual instructions (only needed for CI or scripts)

Section titled “Manual instructions (only needed for CI or scripts)”

If you need a way to download symbols as part of a CI pipeline it’s possible with the following information:

For a given Flutter version you will need the Flutter engine hash to download the symbols. This hash is displayed in shorebird doctor output:

$ shorebird doctor
Shorebird 1.6.49 • git@github.com:shorebirdtech/shorebird.git
Flutter 3.32.5 • revision 44a8ada33bdbe7f25a49e7dcf13c5c1f648129fd
Engine • revision f275acddf709f94ef38af54adb2c1a0a0a90b5c6

In this case, f275acddf709f94ef38af54adb2c1a0a0a90b5c6 is the engine hash.

Assuming engine hash f275acddf709f94ef38af54adb2c1a0a0a90b5c6, the iOS symbols can be downloaded from the following URL:

https://storage.googleapis.com/download.shorebird.dev/flutter_infra_release/flutter/f275acddf709f94ef38af54adb2c1a0a0a90b5c6/ios-release/Flutter.framework.dSYM.zip

For some older Flutter versions, the file is named Flutter.dSYM.zip instead of Flutter.framework.dSYM.zip.

Assuming engine hash f275acddf709f94ef38af54adb2c1a0a0a90b5c6, the Android symbols can be downloaded from the following URLs:

https://download.shorebird.dev/flutter_infra_release/flutter/f275acddf709f94ef38af54adb2c1a0a0a90b5c6/android-arm64-release/symbols.zip https://download.shorebird.dev/flutter_infra_release/flutter/f275acddf709f94ef38af54adb2c1a0a0a90b5c6/android-arm-release/symbols.zip https://download.shorebird.dev/flutter_infra_release/flutter/f275acddf709f94ef38af54adb2c1a0a0a90b5c6/android-x64-release/symbols.zip

On Android, Crashlytics only reports native crashes if you set up NDK crash reporting, which the FlutterFire plugin doesn’t add for you. Unzip each architecture’s symbols.zip into its own subdirectory of one folder, because every zip contains a file named libflutter.so. Then pass that folder to the Firebase CLI, which searches it recursively for .so files:

firebase crashlytics:symbols:upload --app=FIREBASE_APP_ID PATH/TO/SYMBOLS

On iOS, upload the engine’s dSYM zip in the dSYMs tab of the Crashlytics dashboard, or pass it to Crashlytics’ upload-symbols script, which accepts zip archives of dSYMs. See Get readable crash reports for how to run the script, or run it with --help for its options.

The engine symbols above cover Flutter’s C++ code. If you build with --obfuscate or --split-debug-info, your Dart code’s debug information is also removed from the app, and your crash reporting tool needs it to show readable Dart stack traces.

--split-debug-info writes that debug information to a directory, one file per architecture, such as app.android-arm64.symbols or app.ios-arm64.symbols:

shorebird release android --obfuscate --split-debug-info=build/symbols

If you pass --obfuscate without --split-debug-info, Shorebird writes the files to build/shorebird/symbols.

Upload the files in that directory by following your tool’s guide:

shorebird patch accepts the same flags, and an obfuscated release’s patches are obfuscated too. When a patch writes to the same directory as an earlier build, whether the default or a path you pass again, it replaces that build’s files, because the file names are the same. Upload or copy the files after every build, before you run the next one.