Crash Reporting and Symbolicated Stack Traces
Integrate Crashlytics and Sentry with deobfuscation mappings for actionable crash reports.
Why Raw Crash Traces Are Useless
When you ship a Flutter app in release mode, the Dart compiler produces optimized AOT machine code and strips human-readable symbols. A crash that happens in production no longer reports UserRepository.fetchProfile — it reports a hex offset like #00 abs 0000007f9c2a1b40.
- Debug builds keep symbols, so traces are readable locally.
- Release builds obfuscate and strip, so the on-device trace is just addresses.
- To turn those addresses back into method names you need symbolication (native iOS/Android symbols) and deobfuscation (Dart symbol mapping).
This lesson wires up Crashlytics and Sentry so every production crash arrives fully symbolicated and actionable.
Obfuscation and the Symbol Map File
Flutter obfuscation is opt-in. You enable it at build time and Flutter writes a Dart symbol map per target architecture into a directory you choose.
--obfuscaterenames Dart identifiers to short tokens.--split-debug-infowrites the mapping files (e.g.app.android-arm64.symbols) so you can reverse the obfuscation later.
You must archive these symbol files per release. Without the exact file that matches the shipped binary, the trace can never be deobfuscated.
# Build an obfuscated Android release and keep the Dart symbols
flutter build appbundle --release \
--obfuscate \
--split-debug-info=build/symbols/v1.4.0
# iOS equivalent
flutter build ipa --release \
--obfuscate \
--split-debug-info=build/symbols/v1.4.0All lessons in this course
- Build Flavors and Environment Configuration
- Automated Pipelines with Fastlane and GitHub Actions
- Crash Reporting and Symbolicated Stack Traces
- Remote Config, Feature Flags, and Staged Rollouts