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
Getting symbols from the console
Section titled “Getting symbols from the console”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 in the organization that owns the app. The console doesn’t link to Android engine symbols. Use the download URLs instead.
The current URL format for this tab is:
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:
In this case, eaeb4bdcae57b971d6dd7507a3b53e61676b8330 is the engine hash.
Download the symbols from storage.googleapis.com/download.shorebird.dev, which
holds Shorebird’s engine builds. The URLs below use it. Don’t use
download.shorebird.dev for symbols: for some files it redirects to the
upstream Flutter engine’s symbols, which don’t match Shorebird’s engine.
Symbols for iOS
Section titled “Symbols for iOS”Assuming engine hash eaeb4bdcae57b971d6dd7507a3b53e61676b8330, the iOS symbols
can be downloaded from the following URL:
For some older Flutter versions, the file is named Flutter.dSYM.zip instead of
Flutter.framework.dSYM.zip.
Symbols for Android
Section titled “Symbols for Android”Assuming engine hash eaeb4bdcae57b971d6dd7507a3b53e61676b8330, the Android
symbols can be downloaded from the following URLs:
https://storage.googleapis.com/download.shorebird.dev/flutter_infra_release/flutter/eaeb4bdcae57b971d6dd7507a3b53e61676b8330/android-arm64-release/symbols.zip https://storage.googleapis.com/download.shorebird.dev/flutter_infra_release/flutter/eaeb4bdcae57b971d6dd7507a3b53e61676b8330/android-arm-release/symbols.zip https://storage.googleapis.com/download.shorebird.dev/flutter_infra_release/flutter/eaeb4bdcae57b971d6dd7507a3b53e61676b8330/android-x64-release/symbols.zip
Uploading engine symbols to Crashlytics
Section titled “Uploading engine symbols to Crashlytics”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:
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.
Dart symbols for obfuscated builds
Section titled “Dart symbols for obfuscated builds”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:
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 a release’s files
before you run the next build. For patches, pass --split-debug-info with a
directory of their own; see
Reading crashes from patches.
Reading crashes from patches
Section titled “Reading crashes from patches”If you build with --obfuscate or --split-debug-info and a crash happens in
code that a patch changed, your crash reporting tool can’t show the correct
names for those Dart frames, even when you upload every symbol file. On iOS,
code a patch changes runs in Shorebird’s interpreter rather than in your
release’s binary, and crash reporting tools only match symbols to the binary
your release shipped. Frames in code the patch didn’t change still run the
release’s code, so they symbolicate as usual. This applies to both Sentry and
Crashlytics.
Save each patch’s Dart symbol file: it describes the code the patch changed,
which the release’s files don’t. Pass --split-debug-info to
shorebird patch ios. Without it, a patch that isn’t obfuscated writes no
symbol file. An obfuscated patch writes one to build/shorebird/symbols, but it
describes a build step whose output doesn’t ship, so don’t upload or keep it as
the patch’s symbols. The file is named app.ios-arm64.symbols, like the
release’s, so give each patch its own directory, or the next build replaces it:
Keep each release’s and each patch’s directory for as long as that release is installed. If you need a crash in patched code decoded, reach out on Discord.
Android
Section titled “Android”If you build with --obfuscate or --split-debug-info, keep the symbol files
from every shorebird patch android run as well as the release’s. On Android, a
patch replaces your app’s compiled Dart code, so Dart frames in a patched app
come from the patch’s code, not the release’s. Pass --split-debug-info to each
patch, with its own directory:
To read a crash from a patched app, run flutter symbolize on the raw Dart
stack trace with the patch’s symbol file for your device’s architecture, such as
app.android-arm64.symbols. See flutter symbolize --help for how to pass the
trace and the file.
Sentry matches symbols to each crash by build ID, so upload the patch’s symbol
files after every shorebird patch android, the same as after a release.
Crashlytics can’t use a patch’s symbols with firebase_crashlytics 5.2.0 and
newer. The plugin reports the build ID of the libapp.so in your APK, which is
the release’s, so Crashlytics decodes patch frames with the release’s symbols.