Flutter App Works in Debug but Fails in Release
The app runs correctly with flutter run (debug mode) but crashes, behaves incorrectly, or fails to build entirely in release mode (flutter build apk --release, flutter build ipa, or flutter run --release).
The Problem
The app runs correctly with flutter run (debug mode) but crashes, behaves incorrectly, or fails to build entirely in release mode (flutter build apk --release, flutter build ipa, or flutter run --release).
Symptoms
- •App works perfectly via flutter run but crashes immediately in a release build
- •A feature depending on reflection or dynamic class names stops working only in release
- •Release build succeeds but a network call, Firebase feature, or plugin fails at runtime
Why This Happens
- •R8/ProGuard (Android's code shrinker, enabled by default in release builds) removes or renames a class accessed via reflection
- •Environment-specific configuration (API keys, base URLs) that differs between debug and release builds
- •Firebase or other native SDK configuration files not correctly included in the release build variant
- •Code that branches on kDebugMode/kReleaseMode and was never tested in the release path
- •Signing configuration issues specific to release builds
// quick fix
Run flutter run --release locally so you can see the actual crash log, instead of debugging blind from user reports.
This one is frustrating because your instinct is to debug it like a normal bug, and you can't, because the thing that's broken only exists in the build you can't easily attach a debugger to. The first move should always be running flutter run --release locally. It sounds obvious, but a lot of developers skip straight to reading a crash report from a user or a crash-reporting dashboard, which strips out most of the useful detail.
R8 and ProGuard are the most common root cause on Android specifically, and they're sneaky because they don't fail the build. They silently strip a class your code accesses via reflection, and you only find out when that code path actually runs. If a plugin you're using has known ProGuard rules in its documentation and you skipped adding them, that's the first thing to check before you go hunting anywhere else.
The broader lesson here is that "it works in debug" isn't the same as "it works." Debug and release builds genuinely behave differently in Flutter, not just in speed. If your team's testing process never actually runs a release build before shipping, this exact bug will keep coming back under different symptoms.
How to Fix It
1. Reproduce locally with flutter run --release
2. Check for R8/ProGuard-related crashes
3. Diff debug vs release configuration
4. Check native crash logs, not just Flutter's
// common mistakes
- ×Debugging only from crash reports without ever running flutter run --release locally
- ×Disabling code shrinking entirely instead of adding a targeted keep rule
- ×Assuming a release-only crash is a Flutter bug rather than checking native logs first
How to Verify the Fix
- 1.Confirm the release build now runs the previously-failing path successfully via flutter run --release
- 2.Test on a real device, not just an emulator
- 3.If a ProGuard/R8 keep rule was added, confirm app size didn't unexpectedly balloon
Related Problems
Skip the boilerplate
Production-ready Flutter starter kit with Firebase Auth, Firestore, Cloud Functions, push notifications, and Clean Architecture — ship your app in days, not months.
Did this article save you time?
I write these for free. If it helped, a coffee keeps me going — and more articles coming.