kotlinx.serialization icon indicating copy to clipboard operation
kotlinx.serialization copied to clipboard

Update AGP 8.3.1 broken deserialization

Open ravenfeld opened this issue 1 year ago • 7 comments

Hello, I have switched to agp 8.3.1 on my Android project and if I activate the minify I have the following problem.

kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 0: Serializer for subclass

I suppose it's the JSON I'm receiving because there's a key with "type" but it's not used for polymorphism. But what I don't understand is why it works fine without minify.

Thank you for your help.

Environment

  • Kotlin version: [1.9.23]
  • Library version: [1.6.3]
  • Kotlin platforms: [e.g. JVM, JS, Native or their combinations]
  • Android Gradle Plugin version: [8.3.1]

ravenfeld avatar Mar 19 '24 18:03 ravenfeld

If this issue came from AGP configuration, it probably makes more sense to file it to the Google tracker (https://issuetracker.google.com/issues?q=Android%2F). Anyway, it is hard to understand what happened from a single exception message line. If you provide more information (stacktrace, @Serializable classes, project configuration, minimal reproducer), I might be able to help you.

sandwwraith avatar Mar 20 '24 11:03 sandwwraith

That's the mistake. For me it's a problem with proguard and with kotlin serialization because without proguard everything works fine.

Process: com.ravenfeld.maps, PID: 22963
                                                                                                    kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 0: Serializer for subclass 'FeatureCollection' is not found in the polymorphic scope of 'NetworkResponse' at path: $
                                                                                                    Check if class with serial name 'FeatureCollection' exists and serializer is registered in a corresponding SerializersModule.
                                                                                                    To be registered automatically, class 'FeatureCollection' has to be '@Serializable', and the base class 'NetworkResponse' has to be sealed and '@Serializable'.
                                                                                                    JSON input: {
                                                                                                      "type": "FeatureCollection.....
                                                                                                    	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
                                                                                                    	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
                                                                                                    	at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:598)
                                                                                                    	at kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:596)
                                                                                                    	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:85)
                                                                                                    	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:107)
                                                                                                    	at com.jakewharton.retrofit2.converter.kotlinx.serialization.Serializer$FromString.fromResponseBody(Serializer.kt:26)
                                                                                                    	at com.jakewharton.retrofit2.converter.kotlinx.serialization.DeserializationStrategyConverter.convert(DeserializationStrategyConverter.kt:11)
                                                                                                    	at com.jakewharton.retrofit2.converter.kotlinx.serialization.DeserializationStrategyConverter.convert(DeserializationStrategyConverter.kt:7)
                                                                                                    	at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:246)
                                                                                                    	at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:156)
                                                                                                    	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
                                                                                                    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
                                                                                                    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
                                                                                                    	at java.lang.Thread.run(Thread.java:1012)
                                                                                                    	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@f901192, Dispatchers.Main.immediate]

ravenfeld avatar Mar 22 '24 05:03 ravenfeld

For information, no problem with version 7.4.2, but as of version 8.0.0 of gralde I have the problem.

ravenfeld avatar Mar 23 '24 11:03 ravenfeld

It's hard to say this without classes definitions and other setup, but maybe Proguard config is too aggressive and cuts off either your polymorphic module or NetworkResponse serializer completely. Try to add it to keep section of proguard.

sandwwraith avatar Mar 26 '24 12:03 sandwwraith

Yes, it must be too aggressive because it works with this. android.enableR8.fullMode=false

ravenfeld avatar Mar 26 '24 13:03 ravenfeld

Rules supplied by the library should work with full mode, too. Do you have any named companions? (companion object Foo { ... }). Maybe these configurations may help you: https://github.com/Kotlin/kotlinx.serialization/issues/2050#issuecomment-1274445927, https://github.com/Kotlin/kotlinx.serialization?tab=readme-ov-file#android — see 'Example of named companion rules for R8 full mode'

sandwwraith avatar Mar 27 '24 11:03 sandwwraith

We also experienced this issue in our app. I don't have a reproduction sample, but I fairly certain that this is an AGP issue.

We noticed the issue in our latest release, which upgrades AGP from 8.2.1 to 8.4.0. I can also confirm that the issue only happens with R8 "full mode" enabled and we do not use any named companion objects. We also more or less confirmed that the issue is only caused by the AGP 8.4.0 upgrade with "full mode" enabled and not by the Kotlin or kotlinx-serialization version changes in our latest app update.

I reported the issue to Google at https://issuetracker.google.com/issues/340494391

kodebach avatar May 14 '24 15:05 kodebach