free geoip
40

Kotlin App Runs in Debug but Crashes in Release

It’s a common frustration for Android developers: your Kotlin app works perfectly fine in Debug mode, but once you build…

It’s a common frustration for Android developers: your Kotlin app works perfectly fine in Debug mode, but once you build it in Release mode, it suddenly crashes. This issue can be confusing and time-consuming, especially if you are not aware of the differences between Debug and Release builds. In this article, we will explore the main reasons why this happens and provide step-by-step solutions with practical code examples.

Kotlin App Runs in Debug but Crashes in Release

Understanding Debug vs Release Mode

In Android development, Debug and Release builds are compiled differently. The Debug build includes additional logging, debugging symbols, and does not apply aggressive code optimizations. On the other hand, the Release build enables optimization, code shrinking, obfuscation, and resource minification using tools like R8 or ProGuard. This difference often leads to unexpected runtime issues in Release mode.

Key differences:

  • Debug build: no obfuscation, more logging, slower performance.
  • Release build: optimized, code shrunk, class and method names obfuscated.

Common Causes of Crashes in Release Mode

  1. ProGuard / R8 Obfuscation Issues – Classes, methods, or fields may be renamed or removed if not properly kept in the ProGuard rules.
  2. Reflection Usage – Reflection calls may fail if method or field names are obfuscated.
  3. Missing Keep Rules for Third-party Libraries – Some libraries require explicit keep rules to function in Release mode.
  4. NullPointerExceptions due to Optimization – Certain compiler optimizations may cause differences in execution flow.
  5. Uncaught Exceptions – Logging differences may hide runtime errors in Release mode.

Example Case

Let’s say you are using a data class in Kotlin with a JSON parsing library like Gson. In Debug mode, everything works fine, but in Release mode, your app crashes when parsing JSON. This can happen if R8 removes unused fields.

data class User(
    val id: Int,
    val name: String,
    val email: String
)

Typical Crash Log in Release Mode:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING

How to Fix

The fix here is to add a ProGuard keep rule so that the User class and its fields are preserved during obfuscation:

# ProGuard / R8 keep rule
-keep class com.example.app.models.User { *; }

Best Practices to Prevent Release Crashes

  • Check ProGuard/R8 rules for all models and reflection-based code.
  • Enable minify for Debug mode temporarily to catch issues early:
    buildTypes {
    debug {
    minifyEnabled true
    shrinkResources true
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    }

  • Test with ProGuard mappings to debug obfuscated crashes.
  • Log exceptions to crash reporting tools like Firebase Crashlytics.

Full Working Example

Below is an example demonstrating a Retrofit API call that crashes in Release mode without the correct keep rules:

interface ApiService {
    @GET("user/{id}")
    suspend fun getUser(@Path("id") id: Int): User
}

class MainRepository(private val api: ApiService) {
    suspend fun fetchUserData(id: Int): User {
        return api.getUser(id)
    }
}

Required ProGuard Rule:

-keep class com.example.app.models.** { *; }
-keepattributes Signature

Debugging Strategy

  1. Run Release build with logging enabled using adb logcat.
  2. Enable minifyEnabled in Debug to simulate Release environment.
  3. Check proguard-rules.pro for missing keep statements.
  4. Use mapping.txt from the build to de-obfuscate stack traces.

Conclusion

If your Kotlin app works in Debug but crashes in Release, the most likely cause is ProGuard/R8 obfuscation or resource optimization. By understanding the differences between build types and applying correct keep rules, you can ensure your app runs reliably in both modes.

For more information on R8 and ProGuard configuration, check the official Android developer documentation.

rysasahrial

Leave a Reply

Your email address will not be published. Required fields are marked *